JWT 토큰 내용 및 코드 정리
JWT 토큰 발행 절차
•
RefreshToken 관련 코드
// 리프레시 토큰 발급
@PostMapping("/refresh-token")
public ResponseEntity<LoginResponse> refreshToken(HttpServletRequest request, HttpServletResponse response) {
// 토큰 요청
Map<String, String> tokenMap = authService.refreshToken(request);
// 토큰 재발급 불가인 경우 401 에러 반환
if (tokenMap == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
}
// 헤더 Cookie로 refresh 토큰 재발급
tokenUtils.setRefreshTokenCookie(response, tokenMap.get("refreshToken"));
// 응답 Body로 access 토큰 재발급
return ResponseEntity.ok(LoginResponse.builder()
.accessToken(tokenMap.get("refreshToken"))
.build());
}
Java
복사
React
cookie 관련 패키지 설치
yarn add react-cookie
Shell
복사
패키지 설치 후 코드 작성
•
App.js
... 중략 ...
root.render(
// <React.StrictMode>
<ThemeProvider theme={theme}>
<CssBaseline />
<CookiesProvider>
<App />
</CookiesProvider>
</ThemeProvider>
// </React.StrictMode>
);
JavaScript
복사
•
cookieUtil.js 생성
import { Cookies } from "react-cookie";
const cookies = new Cookies();
export const setCookie = (name, value, options) => {
return cookies.set(name, value, {...options});
}
export const getCookie = (name) => {
return cookies.get(name);
}
export const removeCookie = (name) => {
return cookies.remove(name);
}
JavaScript
복사
•
useProvideAuth.jsx
import { useState } from "react"
import { userAPI } from "../api/services/user";
import { jwtDecode } from "jwt-decode";
import { getCookie, removeCookie, setCookie } from "../utils/cookieUtil";
export const useProvideAuth = () => {
const [userInfo, setUserInfo] = useState(null);
const login = async (data, successCallBack = null) => {
try {
const res = await userAPI.login(data);
if (res.status === 200) {
const token = res.data.accessToken;
// localStorage.setItem("token", token);
setCookie('accessToken', token, { path: '/' }); // cookie 설정
const jwtPayload = jwtDecode(token);
console.log(jwtPayload);
setUserInfo({
id: jwtPayload.id,
email: jwtPayload.sub,
role: jwtPayload.role
});
if (successCallBack) {
successCallBack();
}
}
} catch (error) {
console.error(error);
}
}
const logout = (callback = null) => {
// localStorage.removeItem("token");
removeCookie("accessToken");
setUserInfo(null);
if (callback) {
callback();
}
}
const tokenCheck = () => {
// const token = localStorage.getItem("token");
const token = getCookie("accessToken");
if (token) {
const jwtPayload = jwtDecode(token);
if (jwtPayload.exp > Date.now() / 1000) {
return true;
}
}
return false;
}
return {
userInfo,
tokenCheck,
login,
logout
}
}
JavaScript
복사
•
api.js
import axios from "axios";
import { getCookie, setCookie } from "../utils/cookieUtil";
const api = axios.create({
baseURL: `${process.env.REACT_APP_REST_SERVER}`,
withCredentials: true // HttpOnly 쿠키 속성으로 저장된 refreshToken 전송한다.
});
api.interceptors.request.use(
(config) => {
// token 관련 내용
const token = getCookie("accessToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
} else {
delete config.headers.Authorization;
}
return config;
},
(err) => {
return Promise.reject(err);
}
);
api.interceptors.response.use(
(res) => {
return res;
},
async (err) => {
// 원래 403으로 실패했던 요청
const originalReq = err.config;
// 403 에러 처리
if (err.response.status == 403 && !originalReq._retry) {
// 만약에 권한이 없다는 에러가 나오면
try {
// 토큰 재발급 해주도록 할 것이다.
const response = await refreshTokenHandler();
// 정상 재발급 시
if (response.status === 200) {
// token값 로컬스토리지에 저장
// localStorage.setItem("token", response.data.accessToken); // 토큰 재발급
// token 값 쿠키에 저장
setCookie("accessToken", response.data.accessToken);
originalReq.headers.Authorization = `Bearer ${response.data.accessToken}`;
// 실패했던 요청 다시 보내기
return api.request(originalReq);
}
} catch (error) {
console.log("토큰 재발급 실패");
}
console.log("403 에러 권한 없음");
}
return Promise.reject(err);
}
);
const refreshTokenHandler = async () => {
try {
const response = await api.post("/auth/refresh-token");
return response;
} catch (error) {
throw error;
}
}
export default api;
JavaScript
복사
실습
•
엔티티 구성
◦
로그인 (id, email, password, name, role)
◦
상품명 (id, name, price)
•
관리자 → 상품 등록
•
관리자, 회원 → 상품 조회
•
비회원 → 회원가입, 로그인
•
스펙 정리
◦
API
◦
DB 스펙