Spring에서 JWT토근 사용법


<aside> 1️⃣ JSON Web Token (JWT)란?

</aside>

<aside> 2️⃣ Spring Boot와 JWT를 함께 사용하는 방법

</aside>

  1. 먼저, 의존성을 추가해야 한다. Gradle 기반의 프로젝트에서는 build.gradle 파일에 다음과 같이 추가하면 된다.
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'io.jsonwebtoken:jjwt:0.9.1'
}
  1. 그 다음에는 JWT를 사용하여 인증을 처리하는 커스텀 **AuthenticationFilter**와 **AuthenticationProvider**를 구현해야 한다.
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public JwtAuthenticationFilter() {
				// super("/api/**");: "/api/**"와 일치하는 모든 요청에 이 필터를 적용하겠다는 것을 나타냅니다.
        super("/api/**");
    }

    @Override
		// attemptAuthentication(): 이 메소드는 인증 시도를 처리합니다. 이 경우, 클라이언트로부터 "Authorization" 헤더를 받아 JWT 토큰으로 사용합니다.
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException, IOException, ServletException {
        String token = req.getHeader("Authorization");

        if (token == null) {
            throw new RuntimeException("Invalid auth token");
        }

        JwtAuthenticationToken authRequest = new JwtAuthenticationToken(token);

        return getAuthenticationManager().authenticate(authRequest);
    }

    @Override
		// successfulAuthentication(): 인증이 성공적으로 이루어진 후 추가적으로 필요한 동작을 정의합니다. 여기서는 필터 체인에 있는 다음 필터를 호출하도록 설정되어 있습니다.
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
            Authentication auth) throws IOException, ServletException {

        super.successfulAuthentication(req, res, chain, auth);
        chain.doFilter(req, res);
    }
}
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    @Override
		// supports(): 이 메소드는 이 인증 제공자가 특정 인증 타입을 지원하는지 여부를 결정합니다. 여기서는 JwtAuthenticationToken만 지원합니다.
    public boolean supports(Class<?> authentication) {
        return (JwtAuthenticationToken.class.isAssignableFrom(authentication));
    }

    @Override
		// additionalAuthenticationChecks(): 추가적인 인증 검사를 수행하는 곳입니다. 여기서는 아무런 동작도 수행하지 않습니다.
    protected void additionalAuthenticationChecks(UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    }

    @Override
		// retrieveUser(): 인증된 사용자를 검색하는 메소드입니다. 이 메소드에서는 토큰에서 사용자 정보를 파싱하고, 해당 정보를 바탕으로 UserDetails 객체를 생성합니다.
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication;
        String token = jwtAuthenticationToken.getToken();

				// JwtUserDto와 jwtService는 별도로 구현해야 하는 부분들입니다. JwtUserDto는 토큰에서 추출된 사용자 정보를 담는 클래스이고, jwtService는 토큰을 생성하고 검증하는 로직을 갖고 있어야 합니다.
        JwtUserDto parsedUser = jwtService.parseToken(token);

        if (parsedUser == null) {
            throw new JwtTokenMalformedException("JWT token is not valid");
        }

        List<SimpleGrantedAuthority> authorityList = Collections
                .singletonList(new SimpleGrantedAuthority(parsedUser.getRole()));

        return new User(parsedUser.getUsername(), token, authorityList);
    }
}