JWT 토큰 검증 필터 만들기

dasd412·2022년 3월 15일
0

JWT

목록 보기
9/9

구조

첫 로그인 시 구조

JWT 토큰 발급 이후의 구조

코드

첫 로그인에는 UserDetailsService 구현체의 loadUserByUsername()이 호출된다.

하지만 첫 로그인 이후엔 JWT 토큰이 발급되었다. 그 때부터는 UserDetailsService 구현체를 호출하지 않고 JWT 검증 필터를 거치게 되는 것을 확인할 수 있었다.

//시큐리티는 filter 를 가지고 있는데, 그 필터중에 BasicAuthenticationFilter 가 있다.
//권한이나 인증이 필요한 특정 주소를 요청했을 때 위 필터를 무조건 타게 되있다.
//만약에 권한이나 인증이 필요한 주소가 아니라면 이 필터를 안탐.
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {

    private final UserRepository userRepository;

    public JwtAuthorizationFilter(AuthenticationManager authenticationManager, UserRepository userRepository) {
        super(authenticationManager);
        this.userRepository = userRepository;
    }

    //인증이나 권한이 필요한 주소요청이 있을 떄 이 필터를 타게 된다.
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        String jwtHeader = request.getHeader("Authorization");

        //header가 있는지 확인. 없으면 바로 다음 필터로 이동하고 종료.
        if (jwtHeader == null || !jwtHeader.startsWith("Bearer")) {
            chain.doFilter(request, response);
            return;
        }

        //JWT 토큰을 검증해서 정상적인 사용자인지 확인
        String jwtToken = request.getHeader("Authorization").replace("Bearer ", "");
        String username = JWT.require(Algorithm.HMAC512("cos"))//<-시크릿키는 원래 노출 안되게 해야 함. 
                .build()
                .verify(jwtToken)//토큰에 서명하기
                .getClaim("username").asString();

        //서명이 정상적으로 됬다면
        if (username != null) {

            User userEntity = userRepository.findByUsername(username);

            PrincipalDetails principalDetails = new PrincipalDetails(userEntity);
            //Jwt 토큰 서명을 통해서 서명이 정상이면 Authentication 객체를 만들어준다.
            Authentication authentication = new UsernamePasswordAuthenticationToken(principalDetails, null, principalDetails.getAuthorities());
            //강제로 시큐리티 세션에 접근하여 Authentication 객체를 저장한 것.
            SecurityContextHolder.getContext().setAuthentication(authentication);

        }

        chain.doFilter(request, response);
    }
}

위 JWT 검증 필터를 설정용 클래스에 등록해야 한다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
		            ...
								.addFilter(new JwtAuthenticationFilter(authenticationManager()))
                .addFilter(new JwtAuthorizationFilter(authenticationManager(), userRepository))
		            ...
    }
}
profile
시스템 아키텍쳐 설계에 관심이 많은 백엔드 개발자입니다. (Go/Python/MSA/graphql/Spring)

0개의 댓글