[v4] RestAPI 변경 및 JWT 발급

HootJem's avatar
Sep 23, 2024
[v4] RestAPI 변경 및 JWT 발급
먼저 의존성 하나 추가한다.
implementation group: 'com.auth0', name: 'java-jwt', version: '4.3.0'
이후 로그인 할 때 지금까지 사용한 sessionUser를 사용하지 않는다.

토큰

이 유저의 검증을 위해 JWT토큰을 발급한다.
토큰에는 보통 민감하지 않은, 유저를 구분할 수 있는 정보가 담긴 엑세스토큰과 토큰 유효기간 갱신을 위한 리플레시토큰 두 가지를 발급한다.
→ 엑세스토큰 털릴시 잠깐동안 해킹이 될 수는 있어도, 계속될 수는 없음.
→ 만약 리플레시, 엑세스 토큰 둘 다 털리면 1개월 동안 계속털림
 
보안을 위해 여러가지 방법이 있음.
  1. 헤더에 디바이스 아이디, 아이피 등 오는데 이전 로그인 정보를 저장한 뒤 검증함.
  1. but 폰으로 햇다가 컴으로 할 수도 있고, 와이파이로 했다가 lte 이면 아이피가 바뀜
 

JWT 는

발급 시 원본과 해시값을 둘 다 가져간다.
검증할 때 시크릿도 발급함
 
머스태치 세팅을 제거한다.
notion image
 
서비스
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)); }
notion image
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()); }
notion image
notion image

JWT의 전체 구조

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

[HootJem] 개발 기록 블로그