<aside> 1️⃣ Annotation을 직접 만들어서 사용해보자는 결심이 들었다.
</aside>
/**
* 시큐리티 authentication을 주입하는 커스텀 annotation
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface InjectAuthentication {
}
@Aspect
@Component
public class AuthenticationAspect {
@Around("@annotation(com.jinan.profile.config.annotation.InjectAuthentication)")
public Object injectAuthentication(ProceedingJoinPoint joinPoint) throws Throwable {
// 인증 객체 가져오기
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// ThreadLocal을 사용하여 현재 스레드에 인증 객체 저장
CurrentUserContextHolder.set(authentication);
// 메서드를 실행한다.
Object result = joinPoint.proceed();
// 메서드 실행 후 ThreadLocal에서 인증 객체 제거
CurrentUserContextHolder.clear();
return result;
}
}
/**
* CurrentUserContextHolder라는 ThreadLocal을 사용하여 현재 스레드에 인증 객체를 저장하고, 이를 메서드 내부에서 사용할 수 있도록 한다.
*/
public class CurrentUserContextHolder {
private static final ThreadLocal<Authentication> context = new ThreadLocal<>();
public static void set(Authentication authentication) {
context.set(authentication);
}
public static Authentication get() {
return context.get();
}
public static void clear() {
context.remove();
}
}
<aside> 1️⃣ 사용방법
</aside>
// 상단에 이렇게 만들어준 어노테이션을 적는다.
@InjectAuthentication
@PostMapping("/createBoard")
public String createBoard(@RequestBody BoardRequest request) {
// 현재 인증된 사용자의 loginId 가져오기 - 어노테이션이 동작해서 세팅된 값을 가져온다.
Authentication authentication = CurrentUserContextHolder.get();
String loginId = authentication.getName();
// 사용자 로그인id를 사용하여 사용자의 전체 정보 가져오기 (예: 서비스 또는 리포지토리에서)
User user = Optional.ofNullable(userService.findByLoginId(loginId))
.map(User::of)
.orElseThrow(() -> new ProfileApplicationException(ErrorCode.USER_NOT_FOUND));
// 사용자 정보를 request에 추가
request.setUser(user);
boardService.createBoard(request);
return "redirect:/board/list";
}
<aside> 1️⃣ 결론
</aside>
<aside> 1️⃣ 해결방안
</aside>
사실, **SecurityContextHolder
**를 직접 컨트롤러에서 사용하는 것은 좋은 설계 방식은 아닙니다. 컨트롤러는 주로 요청을 처리하고 응답을 반환하는 역할에 집중하게 설계하는 것이 좋습니다. **SecurityContextHolder
**와 같은 보안 관련 로직을 컨트롤러에 직접 넣는 것은 관심사의 분리 원칙에 위배될 수 있습니다.
일반적인 설계 원칙에 따르면: