https://velog.io/@suzhanlee/Oauth2-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0
위의 글과 이어지는 글이다.
JWT를 처리하는 인증 필터를 만들어보자!
Header에 담겨오는 token을 통해 인증절차를 수행하려면, 기존의 Spring Security의 기존 필터인 UsernamePasswordAuthenticationFilter를 사용할 수 없다.
그래서 CustomFilter를 구현할 때 자주 사용하는 OncePerRequestFilter를 상속 받아 Jwt를 처리할 수 있는 필터를 만들었다.
말 그대로 하나의 요청마다 작동하는 필터이다.
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtTokenFactory jwtTokenFactory;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader(TOKEN_HEADER);
try {
authentication(token);
} catch (ExpiredJwtException e) {
request.setAttribute("JWT Exception", JwtExceptionCode.EXPIRED);
} catch (UnsupportedJwtException e) {
request.setAttribute("JWT Exception", JwtExceptionCode.UNSUPPORTED);
} catch (MalformedJwtException e) {
request.setAttribute("JWT Exception", JwtExceptionCode.MALFORMED);
} catch (SignatureException e) {
request.setAttribute("JWT Exception", JwtExceptionCode.INVALID_SIGNATURE);
} catch (IllegalArgumentException e) {
request.setAttribute("JWT Exception", JwtExceptionCode.INVALID);
}
filterChain.doFilter(request, response);
}
private void authentication(String token) {
if (StringUtils.hasText(token) && token.startsWith(TOKEN_PREFIX)) {
token = token.substring(TOKEN_PREFIX.length());
Authentication authentication = jwtTokenFactory.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
JwtTokenFactory
public Authentication getAuthentication(String token) {
Claims claims = parseClaims(token);
String email = claims.get(EMAIL, String.class);
ClientType clientType = ClientType.valueOf(claims.get(CLIENT_TYPE, String.class));
MemberContext memberContext = MemberContext.create(email, clientType);
return new UsernamePasswordAuthenticationToken(memberContext, null, null);
}
private Claims parseClaims(String token) {
return Jwts.parserBuilder()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(token)
.getBody();
}
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtTokenFactory jwtTokenFactory;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.httpBasic().disable();
http
.csrf().disable();
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http
.authorizeHttpRequests(authorize -> authorize.requestMatchers(AUTH_WHITELIST).permitAll()
.anyRequest().authenticated());
http
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenFactory), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(new OauthAuthenticationEntryPoint());
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
MemberController
@GetMapping(ApiPath.MEMBER_MYSELF)
public FindMySelfRs findMySelf(@AuthenticationPrincipal MemberContext memberContext) {
return findMemberService.findMySelf(memberContext);
}