- 23.11.15) TIL - 스프링 숙련 주차 7일차2023년 11월 15일 20시 26분 41초에 업로드 된 글입니다.작성자: oneseel
어제에 이어 개인 프로젝트를 진행했다.
강의를 다시 보면서 쿠키와 세션, jwt를 복습하고, 회원가입, 로그인 API를 구현했다,
security 부분도 공부하면서 프로젝트에 security를 적용하려고 하는데 아직 이해 안되는 부분이 너무 많다.
내일 더 공부해서 security부분을 마무리 지을 생각이다.
진행 상황
- JwtUtil 클래스를 생성
- 회원 가입 API 구현
- 로그인 API 구현
- 아직 Spring security는 미적용
1. JwtUtil 클래스를 생성
1) jwt 데이터
@Component public class JwtUtil { // Jwt 데이터 // Header KEY 값 public static final String AUTHORIZATION_HEADER = "Authorization"; // Token 식별자 public static final String BEARER_PREFIX = "Bearer "; // 토큰 만료시간 private final long TOKEN_TIME = 60 * 60 * 1000L; // 60분 @Value("${jwt.secret.key}") // Base64 Encode 한 SecretKey private String secretKey; private Key key; private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; // 로그 설정 public static final Logger logger = LoggerFactory.getLogger("JWT 관련 로그"); @PostConstruct public void init() { byte[] bytes = Base64.getDecoder().decode(secretKey); key = Keys.hmacShaKeyFor(bytes); }
2) 토큰 생성
// 토큰 생성 public String createToken(String username) { Date date = new Date(); return BEARER_PREFIX + Jwts.builder() .setSubject(username) // 사용자 식별자값(ID) .setExpiration(new Date(date.getTime() + TOKEN_TIME)) // 만료 시간 .setIssuedAt(date) // 발급일 .signWith(key, signatureAlgorithm) // 암호화 알고리즘 .compact(); }
3) jwt Cookie에 저장
// JWT Cookie 에 저장 public void addJwtToCookie(String token, HttpServletResponse res) { try { token = URLEncoder.encode(token, "utf-8").replaceAll("\\+", "%20"); // Cookie Value 에는 공백이 불가능해서 encoding 진행 Cookie cookie = new Cookie(AUTHORIZATION_HEADER, token); // Name-Value cookie.setPath("/"); // Response 객체에 Cookie 추가 res.addCookie(cookie); } catch (UnsupportedEncodingException e) { logger.error(e.getMessage()); } }
4) jwt 토큰 substring
// JWT 토큰 substring public String substringToken(String tokenValue) { if (StringUtils.hasText(tokenValue) && tokenValue.startsWith(BEARER_PREFIX)) { return tokenValue.substring(7); } logger.error("Not Found Token"); throw new NullPointerException("Not Found Token"); }
5) 토큰 검증
// 토큰 검증 public boolean validateToken(String token) { try { Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token); return true; } catch (SecurityException | MalformedJwtException | SignatureException e) { logger.error("Invalid JWT signature, 유효하지 않는 JWT 서명 입니다."); } catch (ExpiredJwtException e) { logger.error("Expired JWT token, 만료된 JWT token 입니다."); } catch (UnsupportedJwtException e) { logger.error("Unsupported JWT token, 지원되지 않는 JWT 토큰 입니다."); } catch (IllegalArgumentException e) { logger.error("JWT claims is empty, 잘못된 JWT 토큰 입니다."); } return false; }
6) 토큰에서 사용자 정보 가져오기
// 토큰에서 사용자 정보 가져오기 public Claims getUserInfoFromToken(String token) { return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody(); }
2. 회원가입 API 구현
1) UserController
// 회원 가입 @PostMapping("/signup") public ResponseEntity<User> signup(@RequestBody SignupRequestDto requestDto) { User user = userService.signup(requestDto); return ResponseEntity.status(HttpStatus.CREATED).body(user); }
2) UserService
// 회원 가입 public User signup(SignupRequestDto requestDto) { String username = requestDto.getUsername(); String password = passwordEncoder.encode(requestDto.getPassword()); // 회원 중복 확인 Optional<User> checkUsername = userRepository.findByUsername(username); if (checkUsername.isPresent()) { throw new IllegalArgumentException("중복된 회원이 존재합니다."); } // 회원 등록 User user = new User(username, password); User saveUser = userRepository.save(user); return saveUser; }
3. 로그인 API 구현
1) UserController
// 로그인 @PostMapping("/login") public ResponseEntity<String> login(@RequestBody LoginRequestDto requestDto, HttpServletResponse res) { String login = userService.login(requestDto, res); return ResponseEntity.ok().body(login); }
2) UserService
// 로그인 public String login(LoginRequestDto requestDto, HttpServletResponse res) { String username = requestDto.getUsername(); String password = requestDto.getPassword(); // 회원 중복 확인 User user = userRepository.findByUsername(username).orElseThrow( () -> new IllegalArgumentException("등록된 회원이 존재합니다.") ); // 비밀번호 확인 if (!passwordEncoder.matches(password, user.getPassword())) { throw new IllegalArgumentException("비밀번호가 일치하지 않습니다."); } // JWT 생성 및 쿠키에 저장 후 Response 객체에 추가 String token = jwtUtil.createToken(user.getUsername()); jwtUtil.addJwtToCookie(token, res); return token; }
'TIL' 카테고리의 다른 글
23.11.17) TIL - 숙련 주차 7일차 (0) 2023.11.17 23.11.16) TIL - 스프링 숙련 주차 8일차 (0) 2023.11.16 23.11.14) TIL - 스프링 숙련주차 6일차 (1) 2023.11.14 23.11.13) TIL - 스프링 숙련주차 5일차 (1) 2023.11.13 23.11.10) TIL - 스프링 숙련 주차 4일차 (0) 2023.11.10 댓글