공부/Spring

[스프링] AuditorAware

Dr.thousand 2023. 11. 22. 15:32
728x90

AuditorAware란 요청이 왔을때, 해당 사용자의 정보를 등록해주는 기능을하는 컴포넌트이다.
아래는 AuditorAware를 빈으로 등록해준다. ApplicationAuditAware는 실제로 동작하는 기능을 정의했다.

@Bean
public AuditorAware<Long> auditorAware() {
    return new ApplicationAuditAware();
}

ApplicationAuditAware에서는 요청이 왔을때, SecurityContextHolder에서 사용자 정보를 불러와서, 사용자번호를 리턴해준다. 간략한 프로세스는 이것이 전부이지만, 그전에 수행해야할 프로세스가 있다.

물론 이전에 SecurityContextHolder에서 setAuthentication을 해주어야한다. 나의 경우 JwtAuthenticationFilter를 통해 등록해주었다. 궁금하다면 아래내용도 함께보자.

public class ApplicationAuditAware implements AuditorAware<Long> {
    @Override
    public Optional<Long> getCurrentAuditor() {
        Authentication authentication =
                SecurityContextHolder
                        .getContext()
                        .getAuthentication();
        if (authentication == null ||
                !authentication.isAuthenticated() ||
                authentication instanceof AnonymousAuthenticationToken
        ) {
            return Optional.empty();
        }

        Member memberPrincipal = (Member) authentication.getPrincipal();
        return Optional.ofNullable(memberPrincipal.getId());
    }
}

스프링 시큐리티를 통해 사용자 정보를 등록해준다.


@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtService jwtService;
    private final UserDetailsService userDetailsService;
    private final TokenRepository tokenRepository;

    @Override
    protected void doFilterInternal(
            @NonNull HttpServletRequest request,
            @NonNull HttpServletResponse response,
            @NonNull FilterChain filterChain
    ) throws ServletException, IOException {
        final String authHeader = request.getHeader("Authorization");
        final String jwt;
        final String userAccount;
        if (authHeader == null ||!authHeader.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);
            return;
        }
        jwt = authHeader.substring(7);
        userAccount = jwtService.extractUsername(jwt);
        if (userAccount != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(userAccount);
            var isTokenValid = tokenRepository.findByToken(jwt)
                    .map(t -> !t.isExpired() && !t.isRevoked())
                    .orElse(false);
            if (jwtService.isTokenValid(jwt, userDetails) && isTokenValid) {
                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );
                authToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails(request)
                );
                SecurityContextHolder.getContext().setAuthentication(authToken);
            }
        }
        filterChain.doFilter(request, response);
    }
}

중요하게 봐야할 부분은

if (userAccount != null && SecurityContextHolder.getContext().getAuthentication() == null)

이 부분이다. 해당 코드의 이하 부분은 userAccount는 존재하지만 SecurityContextHolder에 등록되지 않았을 경우, 해당 계정의 정보를 등록해준다는 의미이다. 이렇게 등록한다면 security context holder에 등록되어 auditAware에서 사용할 수 있게되는것이다.

728x90
반응형

'공부 > Spring' 카테고리의 다른 글

[QueryDSL] QueuryDSL vs JPQL  (0) 2023.12.18
[스프링]Spring Security - SecurityFilterChain  (0) 2023.11.22
[Spring] ControllerAdvice  (0) 2022.09.27
BeanFatory와 ApplicationContext  (0) 2022.03.06
스프링 IoC , DI  (0) 2022.03.03