https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!--jwt 추가-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
인증 오류시 예외 처리
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint{
//인증이 필요한 주소 요청시 인증되지 않았을때 발생하는 예외 처리
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
}
}
## App Properties
app.jwt-secret= JWTSecretKey
app.jwt-expiration-milliseconds = 604800000
워닝 => 프로퍼티 자동생성
생성된 프로퍼티는 META-INF 폴더안에 생성됨
토큰을 생성하는 클래스 만들기
@Component
public class JwtTokenProvider {
@Value("${app.jwt-secret}")
private String jwtSecret;
@Value("${app.jwt-expiration-milliseconds}")
private int jwtExpirationInMs;
// JWT 토큰 생성하기
public String generateToken(Authentication authentication) {
String username = authentication.getName();
Date currentDate = new Date();
Date expireDate = new Date(currentDate.getTime() + jwtExpirationInMs);
String token = Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(expireDate)
.signWith(SignatureAlgorithm.HS512, jwtSecret).compact();
return token;
}
// 토큰으로 유저이름을 얻기
public String getUsernameFromJWT(String token) {
Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();
return claims.getSubject();
}
// 토큰 유효성 검사
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
return true; //토큰이 유효한지 검사해서 오류 발생시 아래에 예외처리됨
} catch(SignatureException ex){
throw new BlogAPIException(HttpStatus.BAD_REQUEST, "유효하지 않은 서명");
} catch (MalformedJwtException ex) {
throw new BlogAPIException(HttpStatus.BAD_REQUEST, "유효하지 않은 토큰");
} catch (ExpiredJwtException ex) {
throw new BlogAPIException(HttpStatus.BAD_REQUEST, "유효시간 지난 토큰");
} catch (UnsupportedJwtException ex) {
throw new BlogAPIException(HttpStatus.BAD_REQUEST, "형식이 맞지않은 토큰");
} catch (IllegalArgumentException ex) {
throw new BlogAPIException(HttpStatus.BAD_REQUEST, "JWT claims string is empty.");
}
}
}
참고 @Bean vs @Component
https://mangkyu.tistory.com/75
참고 인증 실패 시 핸들링
https://lemontia.tistory.com/655
참고 프로퍼티 메타데이터 설정
https://docs.spring.io/spring-boot/docs/current/reference/html/configuration-metadata.html