From da7bccf33232eada082dd7e673395392573a5d56 Mon Sep 17 00:00:00 2001 From: myunsyeya <myunsyeya@ajou.ac.kr> Date: Sun, 8 Dec 2024 02:10:31 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=ED=86=A0=ED=81=B0=20=ED=99=9C?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=EA=B0=84=20=EA=B2=BD=EA=B3=BC=20=EC=8B=9C?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 2 ++ src/api/axios.js | 20 ++++++++++++++++++- src/pages/LoginPage/LoginPage.jsx | 1 + .../LoginPage/components/SignupModal.jsx | 4 +++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index c5fbd38..e631707 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -2,10 +2,12 @@ import React from "react"; import { BrowserRouter as Router } from "react-router-dom"; import Layout from "./layout"; import AppRoutes from "./AppRoutes"; +import TokenExpirationChecker from './components/TokenExpirationChecker'; function App() { return ( <Router> + <TokenExpirationChecker /> <Layout> <AppRoutes /> </Layout> diff --git a/src/api/axios.js b/src/api/axios.js index f30c01f..bc48919 100644 --- a/src/api/axios.js +++ b/src/api/axios.js @@ -10,7 +10,19 @@ const api = axios.create({ api.interceptors.request.use(config => { const token = sessionStorage.getItem('accessToken'); + const expiresAt = sessionStorage.getItem('tokenExpiresAt'); + if (token) { + // 토큰 만료 체크 + if (expiresAt && Date.now() >= parseInt(expiresAt)) { + sessionStorage.removeItem('accessToken'); + sessionStorage.removeItem('tokenExpiresAt'); + if (!window.location.pathname.includes('/login')) { + alert('로그인이 만료되었습니다. 다시 로그인해주세요.'); + window.location.href = '/login'; + } + return Promise.reject('Token expired'); + } config.headers.Authorization = `Bearer ${token}`; } return config; @@ -19,9 +31,15 @@ api.interceptors.request.use(config => { api.interceptors.response.use( response => response, error => { + // 401 에러 처리 if (error.response?.data.statusCode === 401) { sessionStorage.removeItem('accessToken'); - window.location.href = '/login'; + sessionStorage.removeItem('tokenExpiresAt'); + + if (!window.location.pathname.includes('/login')) { + alert('로그인이 필요합니다. 로그인 페이지로 이동합니다.'); + window.location.href = '/login'; + } } return Promise.reject(error); } diff --git a/src/pages/LoginPage/LoginPage.jsx b/src/pages/LoginPage/LoginPage.jsx index 78b43a6..cdbde4f 100644 --- a/src/pages/LoginPage/LoginPage.jsx +++ b/src/pages/LoginPage/LoginPage.jsx @@ -15,6 +15,7 @@ const LoginPage = () => { const data = await axiosLogin({ email, password }); if (data && data.token) { sessionStorage.setItem('accessToken', data.token); + sessionStorage.setItem('tokenExpiresAt', data.expiresAt.toString()); setMessage(`로그인 성공!`); window.location.href = '/'; } else { diff --git a/src/pages/LoginPage/components/SignupModal.jsx b/src/pages/LoginPage/components/SignupModal.jsx index b910070..0370ea0 100644 --- a/src/pages/LoginPage/components/SignupModal.jsx +++ b/src/pages/LoginPage/components/SignupModal.jsx @@ -158,11 +158,13 @@ const SignupModal = ({ onClose }) => { Object.values(formData).some(value => !value)) { return; } - + try { const result = await axiosSignup(formData); if (result) { sessionStorage.setItem('accessToken', result.token); + // 만료 시간도 저장 + sessionStorage.setItem('tokenExpiresAt', result.expiresAt.toString()); window.location.href = '/'; } } catch (error) { -- GitLab