Backend
home
🕔

2024. 9. 11 (JWT 토큰)

생성일
2025/01/24 05:52
태그
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 스펙