현재 내 프로젝트는 문제를 등록,수정,삭제를 접속한 사람이라면 누구나 할 수 있다.
그러나 문제를 등록하는 것은 상관 없으나, 수정하고 삭제하는 기능은 만든 작성자만이 사용할 수 있게 만들고자 하여
수정, 삭제를 할 때 메서드 실행 지점에 권한을 체크하는 모듈을 AOP로 적용해보면 어떨까 해서 찾아보았다.
AOP를 사용하지 않을 경우
권한을 체크해야할 필요가 있는 메서드에 로직을 추가해서 수행해야 할 것이다.
이렇게 되면 권한 체크 로직이 바뀌면 모든 메서드의 코드를 수정해야 하는 번거로움이 발생할 것이다.
그래서 권한을 체크하는 로직은 어떤 메서드든 동일하기 때문에, 따로 분리해서 AOP로 구현하는 것이 좋은 방법이다.
Spring AOP
Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 한다.
쉽게 생각해서 공통적으로 처리하는 로직을 따로 모듈화 해서 원하는 시점, 원하는 메서드에 적용할 수 있게 만들어 주는 것이라고 생각하면 된다.
우선 커스텀 어노테이션을 생성해야 한다.
AuthCheck.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {
}
스프링 시큐리티를 사용할 경우 ROLE을 다룰 필요가 있지만, 나는 프론트에서 OAuth2.0 로그인을 이용하여 Authorization Code를 얻어올 것이기 때문에, 요청으로 들어온 Authorization Code에 대해서만 처리할 것이다.
AuthCheckAspect.java
AuthCheck가 걸린 메서드를 실행할 때 권한을 체크하는 인터셉터
@Slf4j
@Aspect
@RequiredArgsConstructor
@Component
public class AuthCheckAspect {
private static final String AUTHORIZATION = "Authorization";
private final JwtService jwtService;
private final MemberRepository memberRepository;
private final HttpServletRequest httpServletRequest;
@Around("@annotation(wave.myarh.global.auth.AuthCheck)")
public Object authCheck(ProceedingJoinPoint pjp) throws Throwable {
String token = httpServletRequest.getHeader(AUTHORIZATION);
JwtPayload payload = jwtService.getPayload(token);
log.info("AuthCheck(email) : " + payload.getEmail());
Optional<Member> member = memberRepository.findByEmail(payload.getEmail());
if (member.isEmpty()) {
throw new UserAuthenticationException();
}
MemberContext.currentMember.set(member.get());
return pjp.proceed();
}
}
- @Around: 해당 어노테이션이 붙은 메서드가, value에 넣은 어노테이션이 붙은 메서드가 실행 되기 전, 후 동작한다.
활용
다음과 같이 컨트롤러에서 권한 체크를 적용했다.
MemberApiController.java
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/members")
public class MemberApiController {
@AuthCheck
@GetMapping("/check")
public ResponseEntity<?> checkAuth() {
return ResponseEntity.ok().body(ResponseApiDto.of(HttpStatus.OK,"권한_확인"));
}
@AuthCheck
@PostMapping("login")
public ResponseEntity<?> login(@RequestParam @Valid TokenDto tokenDto) {
return ResponseEntity.ok().body(ResponseApiDto.of(
HttpStatus.OK,"토근_검증_완료",null)//todo
);
}
}
'🍃Spring' 카테고리의 다른 글
| [Spring Security] CORS 문제 해결하기 (0) | 2023.04.01 |
|---|---|
| [Spring] 조회수 필드에 대해 동시성 문제 해결하기 (1) | 2023.03.29 |
| [Spring] Business Exception 처리하기 (0) | 2023.02.21 |
| [Spring Boot] 스프링 부트 3 이상에서 Springdocs swagger 적용하기 (0) | 2023.02.19 |
| [Spring Boot] @ResponseStatus와 ResponseEntity (0) | 2023.02.18 |