의존성 추가 implementation 'com.auth0:java-jwt:4.4.0'
dependencies {
// Java jwt lib 가져오
implementation 'com.auth0:java-jwt:4.4.0'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-mustache'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
Jwt lib 추가 (java-jwt)
https://github.com/auth0/java-jwt?tab=readme-ov-file
implementation group: 'com.auth0', name: 'java-jwt', version: '4.3.0'
JwtUtil 클래스 만들기
package com.tenco.blog_v3.common.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.tenco.blog_v3.user.User;
import java.util.Date;
/**
* JWT 토큰의 생성 및 검증을 위한 유틸 클래스 이다.
* 여기서는 알고리즘 HMAC512 알고리즘을 사용한다.
*/
public class JwtUtil {
/**
*
* 주어진 사용자 정보(USER)로 JWT 토큰을 생성한다.
*
* return 생성된 JWT String
*/
public static String create(User user) {
return JWT.create()
// 헤더
.withSubject("blog")
.withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60))
// 페이로드 - 데이터 조각 클레임(사용자 id, 사용자 이름)
.withClaim("id", user.getId())
.withClaim("username", user.getUsername())
// 서명
.sign(Algorithm.HMAC512("tencoding"));
}
public static User verify(String token) {
// JWT 디코딩
DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC512("tencoding"))
.build().verify(token);
// 검증된 JWT 에서 사용자 ID 와 이름 추출 해보자
int id = decodedJWT.getClaim("id").asInt();
String username = decodedJWT.getClaim("username").asString();
return User.builder().id(id).username(username).build();
}
}
UserService
/**
* 로그인 서비스
*
*/
public String signIn(UserRequest.LoginDTO reqDTO) {
User seessionUser = userJPARepository
.findByUsernameAndPassword(reqDTO.getUsername(), reqDTO.getPassword())
.orElseThrow( () -> new Exception401("인증되지 않았습니다"));
return JwtUtil.create(seessionUser);
}
UserController
@PostMapping("/login")
public ResponseEntity<ApiUtil<UserResponse.DTO>> login(@RequestBody UserRequest.LoginDTO reqDto) {
String jwt = userService.signIn(reqDto);
return ResponseEntity.ok()
.header(Define.AUTHORIZATION, Define.BEARER + jwt)
.body(new ApiUtil<>(null));
}
회원 정보 수정
- UserController
/**
* 회원 정보 수정
*/
@PutMapping("/api/users/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") Integer id, @RequestBody UserRequest.UpdateDTO reqDTO, HttpServletRequest request) {
// 헤더에 있는 JWT 토큰을 가져 오기
// 토큰에서 사용자 정보 추출
// 사용자 정보 수정 로직일 그대로 사용
String authorizationHeader = request.getHeader(Define.AUTHORIZATION);
if (authorizationHeader == null || !authorizationHeader.startsWith(Define.BEARER)) {
throw new Exception401("인증 정보가 유효하지 않습니다");
}
// BEARER 문자열과 공백 한칸 제거 처리
String token = authorizationHeader.replace(Define.BEARER, "");
User sessionUser = JwtUtil.verify(token);
if(sessionUser == null) {
throw new Exception401("인증 토큰이 유효하지 않습니다");
}
if(sessionUser.getId() != id) {
throw new Exception403("해당 사용자를 수정할 권한이 없습니다.");
}
// 서비스에 사용자 정보 수정 요청
UserResponse.DTO resDTO = userService.updateUser(id, reqDTO);
return ResponseEntity.ok(new ApiUtil<>(resDTO));
}
- UserService
@Transactional // 트랜잭션 관리
public UserResponse.DTO updateUser(int id, UserRequest.UpdateDTO reqDTO){
// 1. 사용자 조회 및 예외 처리
User user = userJPARepository.findById(id)
.orElseThrow(() -> new Exception404("회원정보를 찾을 수 없습니다"));
// 2. 사용자 정보 수정
user.setPassword(reqDTO.getPassword());
user.setEmail(reqDTO.getEmail());
// 더티 체킹을 통해 변경 사항이 자동으로 반영됩니다.
return new UserResponse.DTO(user);
}
포스트맨 활용
'Spring boot > 개념 공부' 카테고리의 다른 글
JWT 인터셉터 적용 (4) | 2024.11.08 |
---|---|
JWT란 뭘까? (0) | 2024.11.08 |
RestAPI 컨트롤러 요청과 응답 (1) | 2024.11.08 |
공통 응답 DTO 및 예외 처리 구조 만들기 (0) | 2024.11.08 |
RestAPI 주소 변경 및 인터셉터 수정 (0) | 2024.11.08 |