import axios from 'axios'; import { getGlobalStore } from '../../views/pages/AppStore'; const apiClient = axios.create({ baseURL: '/', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, withCredentials: true // 세션 쿠키를 위해 추가 }); const excludeCtxUrls = [ '/sys/cntxtPth/findLatestCntxtPth.json' // Context Path 정보 호출 , '/sys/loginPolicy/getLoginMode.json' // 로그인 모드 정보 호출 , '/sys/loginPolicy/findByStorageMode.json' // 스토리지 모드 정보 호출 ] apiClient.interceptors.request.use( config => { const store = getGlobalStore(); const excludeCtxUrl = excludeCtxUrls.some(url => config.url.includes(url)); const contextPath = store?.state.contextPath || ''; const loginMode = store?.state.loginMode || 'J'; // 기본값은 JWT 모드 if(!excludeCtxUrl) { config.url = contextPath + config.url; } // 로그인 모드에 따른 헤더 설정 if (loginMode === 'J') { config.headers.Authorization = store?.state.authorization; } else if (loginMode === 'S') { delete config.headers.Authorization; config.withCredentials = true; } return config; }, error => { return Promise.reject(error); } ) apiClient.interceptors.response.use( response => { return response; }, async error => { if (!error.response) { return Promise.reject(error); } if (error.response.status == 403 && error.response.data.message == '접근 권한이 없습니다.') { window.history.back(); } const originalReq = error.config; const store = getGlobalStore(); const loginMode = store?.state.loginMode || 'J'; if (originalReq.url.includes('/refresh/tokenReissue.json')) { return Promise.reject(error); } // 핵심: 401 에러 처리를 로그인 모드별로 분기 if (error.response.status === 401 && error.response.data?.message?.toLowerCase().includes('expired') && !originalReq._retry) { originalReq._retry = true; if (loginMode === 'J') { // JWT 모드: 기존 토큰 재발급 로직 try { const res = await axios.post('/refresh/tokenReissue.json', {}, { withCredentials: true }); store.commit('setAuthorization', res.headers.authorization); originalReq.headers.Authorization = store.state.authorization; /** 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 mbr = JSON.parse(jsonPayload); store.commit("setMbrNm", mbr.mbrNm); store.commit('setRoles', mbr.roles); /** jwt토큰 디코딩 끝 **/ return apiClient(originalReq); } catch (refreshError) { handleSessionExpired(store); return Promise.reject(refreshError); } } else if (loginMode === 'S') { // 세션 모드: 토큰 재발급 시도하지 않고 바로 로그인 페이지로 handleSessionExpired(store, '세션이 만료되었습니다.'); return Promise.reject(error); } } return Promise.reject(error); } ) // 세션 만료 처리 함수 function handleSessionExpired(store, message = '세션이 종료되었습니다.') { const redirect = window.location.pathname + window.location.search; sessionStorage.setItem("redirect", redirect); alert(`${message}\n로그인을 새로 해주세요.`); store.commit("setStoreReset"); const admPath = store.state.path?.includes("/adm"); const contextPath = store.state.contextPath || ''; const loginUrl = admPath ? contextPath + "/cmslogin.page" : contextPath + "/login.page"; window.location = loginUrl; } export default apiClient;