Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • bottleneck
  • jwt
  • jwtreal
  • logout
  • main
  • master
  • secure
7 results

Target

Select target project
  • festivelo/festivelo_frontend
1 result
Select Git revision
  • bottleneck
  • jwt
  • jwtreal
  • logout
  • main
  • master
  • secure
7 results
Show changes
Commits on Source (4)
import React, { useState, createContext, useContext } from 'react';
import React, { useState, createContext, useContext, useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
......@@ -61,45 +61,190 @@ function App() {
return null;
});
// 토큰 만료 체크 함수
const checkTokenExpiration = () => {
const token = localStorage.getItem('token');
if (token) {
try {
const decoded = jwt_decode(token);
if (decoded.exp * 1000 < Date.now()) {
// 토큰 만료시 로그아웃과 동일한 효과
localStorage.removeItem('token');
setUser(null);
setIsAuthenticated(false);
toast.info('세션이 만료되었습니다. 다시 로그인해주세요.');
const [lastActivity, setLastActivity] = useState(Date.now());
const INACTIVITY_TIMEOUT = 60000; // 1분
// 사용자 활동 감지 함수
const updateLastActivity = () => {
setLastActivity(Date.now());
};
// // 토큰 만료 체크 함수
// const checkTokenExpiration = () => {
// const token = localStorage.getItem('token');
// if (token) {
// try {
// const decoded = jwt_decode(token);
// if (decoded.exp * 1000 < Date.now()) {
// // 토큰 만료시 로그아웃과 동일한 효과
// localStorage.removeItem('token');
// setUser(null);
// setIsAuthenticated(false);
// toast.info('세션이 만료되었습니다. 다시 로그인해주세요.');
// }
// } catch (error) {
// localStorage.removeItem('token');
// setUser(null);
// setIsAuthenticated(false);
// }
// }
// };
// // 주기적으로 토큰 체크 (30초마다)
// React.useEffect(() => {
// const timer = setInterval(checkTokenExpiration, 30000);
// // 컴포넌트가 언마운트될 때 타이머 정리
// return () => clearInterval(timer);
// }, []);
// 추가--------------------------------
// 토큰 갱신 함수
const refreshToken = async () => {
try {
console.log('토큰 갱신 시도...');
const currentToken = localStorage.getItem('token');
if (!currentToken) {
console.log('토큰이 없습니다.');
return;
}
const response = await fetch('http://localhost:8000/refresh-token', {
method: 'POST',
headers: {
'Authorization': `Bearer ${currentToken}`,
'Content-Type': 'application/json'
}
} catch (error) {
localStorage.removeItem('token');
setUser(null);
setIsAuthenticated(false);
});
if (response.ok) {
const data = await response.json();
localStorage.setItem('token', data.token);
const decoded = jwt_decode(data.token);
console.log('토큰 갱신 성공:', {
만료시간: new Date(decoded.exp * 1000).toLocaleString(),
현재시간: new Date().toLocaleString(),
남은시간: Math.floor((decoded.exp * 1000 - Date.now()) / 1000 / 60) + ''
});
} else {
console.error('토큰 갱신 실패:', response.status);
}
} catch (error) {
console.error('토큰 갱신 실패:', error);
}
};
// 주기적으로 토큰 체크 (30초마다)
React.useEffect(() => {
const timer = setInterval(checkTokenExpiration, 30000);
// 컴포넌트가 언마운트될 때 타이머 정리
return () => clearInterval(timer);
}, []);
// 사용자 활동 감지 - 안되면 다시 활성화
// useEffect(() => {
// const updateActivity = async (e) => {
// // input 태그나 textarea에서의 이벤트는 무시
// if (e.target.tagName.toLowerCase() === 'input' ||
// e.target.tagName.toLowerCase() === 'textarea') {
// console.log('입력 필드 이벤트 무시');
// return;
// }
// const now = Date.now();
// const timeSinceLastRefresh = now - lastTokenRefresh;
// setLastActivity(now);
// console.log('활동 감지:', {
// 현재시간: new Date(now).toLocaleString(),
// 마지막갱신: new Date(lastTokenRefresh).toLocaleString(),
// 경과시간: Math.floor(timeSinceLastRefresh / 1000 / 60) + '분'
// });
// // 마지막 토큰 갱신으로부터 00분 이상 지났을 때만 갱신
// if (timeSinceLastRefresh > (process.env.REACT_APP_TOKEN_EXPIRATION-1) * 60 * 1000) {
// console.log('토큰 갱신 시도...');
// await refreshToken();
// } else {
// console.log(`토큰 갱신까지 ${Math.ceil((process.env.REACT_APP_TOKEN_EXPIRATION-1) - timeSinceLastRefresh/1000/60)}분 남음`);
// }
// };
// console.log('이벤트 리스너 등록됨');
// window.addEventListener('mousemove', updateActivity);
// window.addEventListener('keydown', updateActivity);
// window.addEventListener('click', updateActivity);
// window.addEventListener('scroll', updateActivity);
// window.addEventListener('touchstart', updateActivity);
// return () => {
// console.log('이벤트 리스너 제거됨');
// window.removeEventListener('mousemove', updateActivity);
// window.removeEventListener('keydown', updateActivity);
// window.removeEventListener('click', updateActivity);
// window.removeEventListener('scroll', updateActivity);
// window.removeEventListener('touchstart', updateActivity);
// };
// }, [lastTokenRefresh]);
//안되면 다시 활성화 -------------
const logout = () => {
localStorage.removeItem('token');
setUser(null);
setIsAuthenticated(false);
};
useEffect(() => {
if (isAuthenticated) {
const checkInactivity = () => {
const inactiveTime = Date.now() - lastActivity;
if (inactiveTime > INACTIVITY_TIMEOUT) {
logout();
toast.info('장시간 활동이 없어 자동 로그아웃되었습니다.');
}
};
const updateActivity = () => {
setLastActivity(Date.now());
};
// 사용자 활동 감지를 위한 이벤트 리스너
window.addEventListener('mousemove', updateActivity);
window.addEventListener('keydown', updateActivity);
window.addEventListener('click', updateActivity);
window.addEventListener('scroll', updateActivity);
window.addEventListener('touchstart', updateActivity);
// 비활성 상태 체크 인터벌 설정 (5초마다)
const inactivityCheck = setInterval(checkInactivity, 5000);
return () => {
// 이벤트 리스너 및 인터벌 정리
window.removeEventListener('mousemove', updateActivity);
window.removeEventListener('keydown', updateActivity);
window.removeEventListener('click', updateActivity);
window.removeEventListener('scroll', updateActivity);
window.removeEventListener('touchstart', updateActivity);
clearInterval(inactivityCheck);
};
}
}, [isAuthenticated, lastActivity, logout]);
// 비활성 시간 체크
useEffect(() => {
const checkInactivity = () => {
const inactiveTime = Date.now() - lastActivity;
if (inactiveTime > process.env.REACT_APP_TOKEN_EXPIRATION * 60 * 1000) { // 토큰 만료시간
logout();
toast.info('장시간 활동이 없어 로그아웃되었습니다.');
}
};
const interval = setInterval(checkInactivity, 30000); // 30초마다 체크
return () => clearInterval(interval);
}, [lastActivity]);
//--------------------------------
const login = (userData) => {
setUser(userData);
setIsAuthenticated(true);
};
const logout = () => {
localStorage.removeItem('token');
setUser(null);
setIsAuthenticated(false);
};
return (
<AuthContext.Provider value={{ isAuthenticated, user, login, logout }}>
<ToastContext.Provider value={toast}>
......