forked from UMC-EWHA/umc-spring-3rd
-
Notifications
You must be signed in to change notification settings - Fork 0
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
aec97bf
commit a85421e
Showing
8 changed files
with
128 additions
and
3 deletions.
There are no files selected for viewing
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,7 @@ | ||
package umc.crud.config.secret; | ||
|
||
public class Secret { | ||
// 터미널에 $ openssl rand -hex 64 명령어를 입력해 랜덤 문자열 생성해 secret key로 사용 | ||
public static String JWT_SECRET_KEY = "5fb7652d9ffd2098bcdd5434c9a9fbd5a84832a25b3897836fd50ba2f780588d4febfa3be27cd08bcd70d7ffffa8dca268a642a86a0dc838896d613fb52d3114"; | ||
public static String USER_PASSWORD_KEY = ""; | ||
} |
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
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
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 |
---|---|---|
|
@@ -48,7 +48,7 @@ public PostUserRes createUser(PostUserReq postUserReq) throws BaseException { | |
try { | ||
// 암호화: postUserReq에서 제공받은 비밀번호를 암호화해 DB에 저장 | ||
// ex) password123 -> dfhsjfkjdsnj4@[email protected] | ||
pwd = new AES128(Secret.USER_INFO_PASSWORD_KEY).encrypt(postUserReq.getPassword()); // 암호화 | ||
pwd = new AES128(Secret.USER_PASSWORD_KEY).encrypt(postUserReq.getPassword()); // 암호화 | ||
postUserReq.setPassword(pwd); | ||
} catch (Exception ignored) { // 암호화에 실패할 경우 에러 발생 | ||
throw new BaseException(PASSWORD_ENCRYPTION_ERROR); | ||
|
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 |
---|---|---|
|
@@ -9,4 +9,5 @@ | |
@AllArgsConstructor | ||
public class PostLoginRes { | ||
private int userIdx; | ||
private String jwt; | ||
} |
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 |
---|---|---|
|
@@ -9,4 +9,5 @@ | |
@AllArgsConstructor | ||
public class PostUserRes { | ||
private int userIdx; | ||
private String jwt; | ||
} |
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,45 @@ | ||
package umc.crud.utils; | ||
|
||
import javax.crypto.BadPaddingException; | ||
import javax.crypto.Cipher; | ||
import javax.crypto.IllegalBlockSizeException; | ||
import javax.crypto.NoSuchPaddingException; | ||
import javax.crypto.spec.IvParameterSpec; | ||
import javax.crypto.spec.SecretKeySpec; | ||
import java.security.InvalidAlgorithmParameterException; | ||
import java.security.InvalidKeyException; | ||
import java.security.Key; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.util.Base64; | ||
|
||
import static java.nio.charset.StandardCharsets.UTF_8; | ||
|
||
// 고급 암호화 표준 | ||
// 참고) https://sunghs.tistory.com/119 | ||
public class AES128 { | ||
private final String ips; | ||
private final Key keySpec; | ||
|
||
public AES128(String key) { | ||
byte[] keyBytes = new byte[16]; | ||
byte[] b = key.getBytes(UTF_8); | ||
System.arraycopy(b, 0, keyBytes, 0, keyBytes.length); | ||
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); | ||
this.ips = key.substring(0, 16); | ||
this.keySpec = keySpec; | ||
} | ||
//암호화 관련 함수 | ||
public String encrypt(String value) throws NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException { | ||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | ||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ips.getBytes())); | ||
byte[] encrypted = cipher.doFinal(value.getBytes(UTF_8)); | ||
return new String(Base64.getEncoder().encode(encrypted)); | ||
} | ||
//복호화 관련함수 | ||
public String decrypt(String value) throws NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException { | ||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | ||
cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ips.getBytes(UTF_8))); | ||
byte[] decrypted = Base64.getDecoder().decode(value.getBytes()); | ||
return new String(cipher.doFinal(decrypted), UTF_8); | ||
} | ||
} |
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,71 @@ | ||
package umc.crud.utils; | ||
|
||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.Jws; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.SignatureAlgorithm; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.context.request.RequestContextHolder; | ||
import org.springframework.web.context.request.ServletRequestAttributes; | ||
import umc.crud.config.BaseException; | ||
import umc.crud.config.secret.Secret; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import java.util.Date; | ||
|
||
import static umc.crud.config.BaseResponseStatus.*; | ||
|
||
@Service | ||
public class JwtService { | ||
|
||
/** | ||
* JWT 생성 | ||
* @param userIdx | ||
* @return String | ||
*/ | ||
public String createJwt(int userIdx){ | ||
Date now = new Date(); | ||
return Jwts.builder() | ||
.setHeaderParam("type","jwt") // type=jwt로 설정 | ||
.claim("userIdx",userIdx) // payload에 담길 데이터(userIdx로 전달받은 값) | ||
.setIssuedAt(now) // 발급 시간 | ||
.setExpiration(new Date(System.currentTimeMillis()+1*(1000*60*60*24*365))) // 해당 JWT 만료 시간(1년 뒤로 설정) | ||
.signWith(SignatureAlgorithm.HS256, Secret.JWT_SECRET_KEY) // 서명 알고리즘(HS256), 비밀키 | ||
.compact(); // 토큰 생성 | ||
} | ||
|
||
/** | ||
* Header에서 X-ACCESS-TOKEN으로 JWT 값 추출 | ||
* @return String | ||
*/ | ||
public String getJwt(){ | ||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); | ||
return request.getHeader("X-ACCESS-TOKEN"); // 프론트에서 "X-ACCESS-TOKEN"라는 이름의 header에 담아 넘겨주었다고 가정, Postman 돌릴 때 header에 값 넣어주기 | ||
} | ||
|
||
/** | ||
* JWT에서 userIdx 추출 | ||
* @return int | ||
* @throws BaseException | ||
*/ | ||
public int getUserIdx() throws BaseException { | ||
//1. 헤더에서 JWT 추출 | ||
String accessToken = getJwt(); | ||
if(accessToken == null || accessToken.length() == 0){ | ||
throw new BaseException(EMPTY_JWT); | ||
} | ||
|
||
// 2. JWT parsing | ||
Jws<Claims> claims; | ||
try{ | ||
claims = Jwts.parser() | ||
.setSigningKey(Secret.JWT_SECRET_KEY) | ||
.parseClaimsJws(accessToken); | ||
}catch (Exception ignored) { | ||
throw new BaseException(INVALID_JWT); | ||
} | ||
|
||
// 3. userIdx 추출 | ||
return claims.getBody().get("userIdx",Integer.class); // jwt에서 userIdx 추출합 | ||
} | ||
} |