-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cedae93
commit aceda13
Showing
1 changed file
with
113 additions
and
0 deletions.
There are no files selected for viewing
113 changes: 113 additions & 0 deletions
113
server-toy-project/src/main/java/com/gdsc_teamb/servertoyproject/jwt/JwtTokenProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package com.gdsc_teamb.servertoyproject.jwt; | ||
|
||
import io.jsonwebtoken.*; | ||
import io.jsonwebtoken.io.Decoders; | ||
import io.jsonwebtoken.security.Keys; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.GrantedAuthority; | ||
import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
import org.springframework.security.core.userdetails.User; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.stereotype.Component; | ||
import java.security.Key; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.Date; | ||
import java.util.stream.Collectors; | ||
|
||
@Slf4j | ||
@Component | ||
public class JwtTokenProvider { | ||
|
||
private final Key key; | ||
|
||
public JwtTokenProvider(@Value("${jwt.secret}") String secretKey) { | ||
byte[] keyBytes = Decoders.BASE64.decode(secretKey); // Base64 형식으로 인코딩된 Secret Key를 디코딩한 후, byte array를 반환 | ||
this.key = Keys.hmacShaKeyFor(keyBytes); // HMAC 알고리즘을 적용 | ||
} | ||
|
||
// 유저 정보를 가지고 AccessToken, RefreshToken 생성 | ||
public TokenInfo generateToken(Authentication authentication) { | ||
// 권한 가져오기 | ||
String authorities = authentication.getAuthorities().stream() | ||
.map(GrantedAuthority::getAuthority) | ||
.collect(Collectors.joining(",")); | ||
|
||
long now = (new Date()).getTime(); | ||
|
||
// Access Token 생성 | ||
Date accessTokenExpiresIn = new Date(now + 1000 * 60 * 60); // 토큰 만료 시간 (1h) | ||
|
||
String accessToken = Jwts.builder() | ||
.setSubject(authentication.getName()) // 토큰 제목 | ||
.claim("auth", authorities) // JWT에 포함 시킬 Custom Claim를 추가 (인증된 사용자와 관련된 정보 추가) | ||
.setExpiration(accessTokenExpiresIn) // 토큰 만료 시간 설정 | ||
.signWith(key, SignatureAlgorithm.HS256) // Sign을 위한 Key 객체 설정 (암호화 알고리즘 + secretKey = signature) | ||
.compact(); // 토큰 생성 및 직렬화 | ||
|
||
// Refresh Token 생성 | ||
String refreshToken = Jwts.builder() | ||
.setExpiration(new Date(now + 1000 * 60 * 60 * 24 * 7)) // 토큰 만료 시간 (7d) | ||
.signWith(key, SignatureAlgorithm.HS256) | ||
.compact(); | ||
|
||
return TokenInfo.builder() | ||
.grantType("Bearer") | ||
.accessToken(accessToken) | ||
.refreshToken(refreshToken) | ||
.build(); | ||
} | ||
|
||
// JWT 토큰을 복호화하여 토큰에 들어있는 정보를 꺼내는 메서드 | ||
public Authentication getAuthentication(String accessToken) { | ||
// 토큰 복호화 | ||
Claims claims = parseClaims(accessToken); | ||
|
||
if (claims.get("auth") == null) { | ||
throw new RuntimeException("권한 정보가 없는 토큰입니다."); | ||
} | ||
|
||
// 클레임에서 권한 정보 가져오기 | ||
Collection<? extends GrantedAuthority> authorities = | ||
Arrays.stream(claims.get("auth").toString().split(",")) | ||
.map(SimpleGrantedAuthority::new) | ||
.collect(Collectors.toList()); | ||
|
||
// UserDetails 객체를 만들어서 Authentication 리턴 | ||
UserDetails principal = new User(claims.getSubject(), "", authorities); | ||
return new UsernamePasswordAuthenticationToken(principal, "", authorities); | ||
} | ||
|
||
// 토큰 정보 검증 | ||
public boolean validateToken(String token) { | ||
if(token != null) | ||
{ | ||
try { | ||
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token); | ||
return true; | ||
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { | ||
log.info("잘못된 JWT 서명입니다.", e); | ||
} catch (ExpiredJwtException e) { | ||
log.info("만료된 JWT 토큰입니다.", e); | ||
} catch (UnsupportedJwtException e) { | ||
log.info("지원되지 않는 JWT 토큰입니다.", e); | ||
} catch (IllegalArgumentException e) { | ||
log.info("JWT 토큰이 잘못되었습니다.", e); | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
private Claims parseClaims(String accessToken) { | ||
try { | ||
return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(accessToken).getBody(); | ||
} catch (ExpiredJwtException e) { | ||
return e.getClaims(); | ||
} | ||
} | ||
|
||
} |