스프링 공부/게시판 프로젝트 만들기

[스프링] 10. JWT를 구현하기. 찐막: 필터만들기와 SecurityConfiguration에 JWT 추가하기

장아장 2023. 1. 9. 14:21

일단, 필터를 만들어서 우리가 해야할 일을 알아야 한다.

 

토큰을 받아왔을 때, "Authorization"으로 되어있는 헤더를 가져온다. 

이 헤더에 대한 인증 방식이 우리의 토큰과 같을 경우, 토큰 부분을 떼고 나머지를 가져온다. 

이 부분이 사용 가능한 토큰인 경우, 사용자의 인증정보를 Authentication에 담아주면 된다. 

 

이러한 동작을 필터에서 만들어주면 된다. 

일단, 토큰을 받아왔을 때 필요한 부분만을 가져와주는 동작을 만들었다. 

private String resolveToken(HttpServletRequest request) {
    String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
    if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(BEARER_PREFIX)) {
        return bearerToken.substring(7);
    }
    return null;
}

AUTHORIZATION_HEADER와 BEARER_PREFIX는 상수로, "Authorization", "Bearer " 로 해두었다. 

 

코드를 정리하자면, 요청에서 Authorization이라는 변수로 되어있는 헤더를 가져온다. 

이 헤더의 부분이 Bearerd이라면, 그 뒷 부분들을 가져오는 것이다. 

 

이 때 유의해야 할 것은, 여기에서 말하는 헤더와, 토큰의 헤더는 다르다. 

요청이 있을 때, 

  • 헤더
    • 토큰
      • HEADER
      • PAYLOAD
      • SIGNATURE
  • 바디

 

의 구조로 있으므로, 토큰의 나머지 부분들을 가져온다고 생각하면 된다. 

 

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
    String jwt = resolveToken(request);
    if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
        Authentication authentication = tokenProvider.getAuthentication(jwt);
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }
    filterChain.doFilter(request, response);
}

 

가져온 상태에서, 토큰의 Authentication을 담아주어야 한다. 

담는 장소는, SecurityContextHolder안에, SecurityContext안에, Authentication을 설정해주면 된다. 

 

이후, 필터를 마저 동작시키면 된다.

 

 

 

 

 

 

이런 필터를 만들었다면, 이 필터를 필터체인에 등록해주어야 한다. 

 

@RequiredArgsConstructor
public class JwtSecurityConfig {

    private final TokenProvider tokenProvider;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        http.addFilterBefore(new JwtFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
}

동작과정은 단순하다.

필터 체인에서 Authentication정보, 혹은 그 속에 들어있는 Member(사용자)의 Authorization(즉, 역할 같은 것)을 확인하고 이를 통한 필터링을 해야하는데, 이를 사전에 넣어주어야 하는 것이다. 

 

그러기 위해서, 모든 필터 이전에 이러한 필터를 추가해줄 것이다. 

 

http.addFilterBefore라는 메서드는 모든 필터 이전에 동작시킬 필터를 추가해준다. 

이 점을 이용해, JwtFilter를 넣어준다. 

이를 통해 사용자의 토큰을 필터링해주고, Authentication을 설정해줄 수 있다. 

 

이렇게 JWT에 대한 기본적인 설정을 해두었다. 

그렇다고 Security가 완전히 끝난 것은 아니다. 

요청에 대한 권한들을 설정할 때, api마다 권한을 다르게 하기 위한 설정등을 SecurityConfiguration에 설정해야 하기 때문에, 계속해서 건드릴 예정이다. 

 

그러기 위해, 엔티티들을 만들고, 이 엔티티에 대한 로직들을 만들고 모든 로직들이 동작하는 컨트롤러를 둔 다음, 그 컨트롤러 요청에 관한 권한을 조작하는 방식으로 프로젝트의 진행 방향을 설정해야 겠다.