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 스펙


