import axios from 'axios'; import store from "../../views/pages/AppStore"; // 공통 API 요청 인터셉터 설정 const apiClient = axios.create({ baseURL: '/', headers: { 'Content-Type': 'application/json; charset=UTF-8', } }); // 요청 인터셉터 apiClient.interceptors.request.use( config => { // 요청 전에 토큰을 헤더에 추가 const token = store.state.authorization; if (token) { config.headers.Authorization = store.state.authorization; } return config; }, error => { return Promise.reject(error); } ); // 응답 인터셉터 apiClient.interceptors.response.use( response => response, async error => { if (!error.response) return Promise.reject(error); const { status, data } = error.response; const originalReq = error.config; // 로그인 요청은 토큰 리프레시 대상이 아님 if (originalReq?.skipAuthRefresh) { return Promise.reject(error); } // 권한 없음 if (status === 403 && data.message === '접근 권한이 없습니다.') { window.history.back(); return Promise.reject(error); } // 리프레시 토큰 요청은 재시도하지 않음 if (originalReq.url.includes('/refresh/tknReissue.json')) { return Promise.reject(error); } // 토큰 만료 시 한 번만 재시도 if (status === 401 && !originalReq._retry) { originalReq._retry = true; try { // 리프레시 요청은 별도 인스턴스로 처리 (apiClient로 하면 무한 루프 위험) const refreshClient = axios.create(); const res = await refreshClient.post('/refresh/tknReissue.json'); const newToken = res.headers.authorization; // 토큰 저장 store.commit('setAuthorization', newToken); originalReq.headers.Authorization = newToken; // 유저 정보 다시 저장 /** jwt토큰 디코딩 **/ const base64String = store.state.authorization.split('.')[1]; const base64 = base64String.replace(/-/g, '+').replace(/_/g, '/'); const jsonPayload = decodeURIComponent(atob(base64).split('').map(c => { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); const user = JSON.parse(jsonPayload); store.commit("setUserInfo", { userId: user.userId, loginId: user.loginId, userNm: user.userNm, roles: Array.isArray(user.roles) ? user.roles.map(r => r.authority) : [], }); // 실패했던 요청 재시도 return apiClient(originalReq); } catch (refreshError) { // 로그인 요청은 리프레시 실패 시에도 처리 if (originalReq?.url?.includes('/login.json')) { return Promise.reject(refreshError); } // 리프레시 실패 - 세션 만료 처리 sessionStorage.setItem("redirect", window.location.pathname + window.location.search); alert('세션이 종료 되었습니다.\n로그인을 새로 해주세요.'); store.commit("setStoreReset"); localStorage.clear(); sessionStorage.clear(); window.location.href = '/login.page'; return Promise.reject(refreshError); } } return Promise.reject(error); } ); export default apiClient;