먼저 의존성 하나 추가한다.
implementation group: 'com.auth0', name: 'java-jwt', version: '4.3.0'
이후 로그인 할 때 지금까지 사용한 sessionUser를 사용하지 않는다.
토큰
이 유저의 검증을 위해 JWT토큰을 발급한다.
토큰에는 보통 민감하지 않은, 유저를 구분할 수 있는 정보가 담긴
엑세스토큰
과
토큰 유효기간 갱신을 위한 리플레시토큰
두 가지를 발급한다.→ 엑세스토큰 털릴시 잠깐동안 해킹이 될 수는 있어도, 계속될 수는 없음.
→ 만약 리플레시, 엑세스 토큰 둘 다 털리면 1개월 동안 계속털림
보안을 위해 여러가지 방법이 있음.
- 헤더에 디바이스 아이디, 아이피 등 오는데 이전 로그인 정보를 저장한 뒤 검증함.
- but 폰으로 햇다가 컴으로 할 수도 있고, 와이파이로 했다가 lte 이면 아이피가 바뀜
JWT 는
발급 시 원본과 해시값을 둘 다 가져간다.
검증할 때 시크릿도 발급함
머스태치 세팅을 제거한다.

서비스
public User 로그인(UserRequest.LoginDTO loginDTO) {
// 1. 해당 유저가 있는지 조회
User user = userRepository.findByUsernameAndPassword(loginDTO.getUsername(), loginDTO.getPassword())
.orElseThrow(() -> new Exception401("인증되지 않았습니다"));
// 2. 조회가 되면 JWT만들고 응답
// 비밀인부분, 털리면안대
String accessToken = JwtUtil.create(user);
return user;
}
컨트롤러
@PostMapping("/login")
public ResponseEntity<?> login(@Valid @RequestBody UserRequest.LoginDTO loginDTO, Errors errors) {
User accessToken = userService.로그인(loginDTO);
return ResponseEntity.ok()
.header("Authorization", "Bearer"+accessToken)
.body(Resp.ok(null));
}

api 이기 때문에 리턴 타입 변경 및 매개변수 수정.
유틸
public class JwtUtil {
public static String create(User user){
String accessToken= JWT.create()
.withSubject("바보")
.withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 7)) // 1주일
.withClaim("id", user.getId()) // payload
.sign(Algorithm.HMAC512("metacoding"));
return accessToken;
}
// 검증 테스트
public static User verify(String jwt){
DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC512("metacoding")).build().verify(jwt);
int id = decodedJWT.getClaim("id").asInt();
String username = decodedJWT.getClaim("username").asString();
return User.builder()
.id(id)
.username(username)
.build();
}
}
테스트
public void create_test(){
User user = User.builder().id(1).username("ssar").build();
String accessToken = JwtUtil.create(user);
System.out.println(accessToken);
}
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiLrsJTrs7QiLCJpZCI6MSwiZXhwIjoxNzI3NDAxMDc4fQ.1Ajxs0WTdg40m1CNloFCty1adboo5FpE7qMS0-IfICKFO10xO0u_0dn5R-Cfb9kNdramh15HxGg4kyC7cadJfw
@Test
public void verify_test(){
String accessToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiLrsJTrs7QiLCJpZCI6MSwiZXhwIjoxNzI3NDAxMDc4fQ.1Ajxs0WTdg40m1CNloFCty1adboo5FpE7qMS0-IfICKFO10xO0u_0dn5R-Cfb9kNdramh15HxGg4kyC7cadJfw";
User user = JwtUtil.verify(accessToken);
System.out.println(user.getId());
System.out.println(user.getUsername());
}


JWT의 전체 구조
최종적으로 JWT는 다음과 같이 세 부분을 마침표(.)로 연결한 문자열이다.
{Base64Url로 인코딩된 헤더}.{Base64Url로 인코딩된 페이로드}.{서명}
Share article