스프링 시큐리티(Spring Security)를 사용할 때, 요청이 서버로 들어오고 나가는 과정을 필터 체인이 담당한다. 이 필터 체인에서 JwtFilter
는 JWT 토큰을 인증하고, ExceptionTranslationFilter
는 인증 과정에서 발생하는 예외를 처리한다. 그렇다면, JwtFilter는 필터 체인에서 어디에 배치해야 할까?
1. JWT 필터(JwtFilter)란?
JwtFilter
는 클라이언트가 요청에 포함한 JWT(JSON Web Token)를 확인하고, 유효하다면 해당 사용자의 인증 정보를 스프링 시큐리티의 SecurityContextHolder
에 저장하는 역할을 한다. 이를 통해 클라이언트 요청이 인증된 사용자로부터 온 것임을 보장할 수 있다.
public class JwtFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String token = resolveToken(request);
if (token != null && JwtUtil.validateToken(token)) {
Authentication auth = JwtUtil.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
filterChain.doFilter(request, response);
}
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
return bearerToken != null && bearerToken.startsWith("Bearer ") ? bearerToken.substring(7) : null;
}
}
2. 예외 처리 필터(ExceptionTranslationFilter)란?
ExceptionTranslationFilter
는 스프링 시큐리티에서 발생하는 인증 및 권한 예외를 처리하는 필터이다. 인증되지 않은 사용자가 보호된 리소스에 접근하려고 할 때 AuthenticationException
이나 AccessDeniedException
이 발생할 수 있는데, 이때 ExceptionTranslationFilter
가 해당 예외를 처리하여 적절한 응답을 반환한다. 예를 들어, 인증되지 않은 사용자가 보호된 페이지에 접근하려 할 때 401 Unauthorized 응답을 반환하거나 로그인 페이지로 리다이렉트할 수 있다.
3. 결론
JwtFilter
는 반드시 ExceptionTranslationFilter
보다 먼저 실행되어야 한다. 그 이유는 다음과 같다:
- JWT 인증 처리:
JwtFilter
는 클라이언트가 보낸 JWT 토큰을 먼저 검증하고, 인증 정보를SecurityContextHolder
에 설정한다. 따라서 예외 처리 필터보다 먼저 실행되어야만 인증을 시도할 수 있다. - 예외 처리: JwtFilter에서 인증 정보가 설정되지 않으면 이후 요청에서 예외가 발생할 수 있다. 이때 ExceptionTranslationFilter가 그 예외를 처리하여 적절한 응답을 반환한다.
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// JwtFilter를 ExceptionTranslationFilter보다 먼저 실행하도록 추가
http.addFilterBefore(new JwtFilter(), ExceptionTranslationFilter.class);
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin() // 로그인 설정
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
'WIL > 웹 개발' 카테고리의 다른 글
WAI-ARIA: Role과 Aria-Label이란? (1) | 2024.11.19 |
---|---|
Spring 애플리케이션 배포 시 GitHub Actions 환경 변수 설정법 (1) | 2024.11.04 |
Spring Boot 3 애플리케이션을 AWS Elastic Beanstalk에 배포했을 때의 Bad Gateway 문제 해결 과정 (2) | 2024.10.31 |
2024년 10월 1일 이후 Github Action과 AWS Beanstalk를 사용한 CI/CD (1) | 2024.10.29 |
Presigned URL을 사용한 파일 업로드 구현 (0) | 2024.10.15 |