- CSRF 토큰 저장소 쿠키 → 세션 전환 및 클라이언트 로직 수정
eapim-portal CI / build (push) Has been cancelled
eapim-portal Test / test (push) Has been cancelled

- error 페이지 텍스트 동적 처리 추가 (prod 환경 구분)
- CSRF 메타 데이터 추가 및 JS/AJAX CSRF 로직 일원화
This commit is contained in:
Rinjae
2026-06-22 14:19:32 +09:00
parent 6694715195
commit 5adfd42751
7 changed files with 125 additions and 20 deletions
@@ -14,8 +14,9 @@
const counterEl = document.getElementById('djbCommentCharCounter');
function getCsrfToken() {
const match = document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]+)/);
return match ? decodeURIComponent(match[1]) : '';
// 세션 기반 CSRF: 쿠키 대신 <meta name="_csrf">에서 토큰을 읽는다.
const meta = document.querySelector('meta[name="_csrf"]');
return meta ? meta.getAttribute('content') : '';
}
function fetchJson(url, options) {
@@ -329,17 +329,10 @@
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
// Get CSRF token from cookie
// 세션 기반 CSRF: 쿠키 대신 <meta name="_csrf">에서 토큰을 읽는다.
function getCsrfToken() {
var name = 'XSRF-TOKEN=';
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.indexOf(name) === 0) {
return decodeURIComponent(cookie.substring(name.length));
}
}
return '';
var meta = document.querySelector('meta[name="_csrf"]');
return meta ? meta.getAttribute('content') : '';
}
// Validate date range (max 40 days)
@@ -210,12 +210,13 @@
</div>
<!-- Error Title -->
<h1 class="error-title">일시적인 장애로 서비스가 중단되었습니다.</h1>
<h1 class="error-title" th:text="${errorTitle ?: '서비스 처리 중 오류가 발생했습니다.'}">
서비스 처리 중 오류가 발생했습니다.
</h1>
<!-- Error Description -->
<p class="error-description">
서비스 이용에 불편을 드려 죄송합니다.<br>
빠른 서비스를 제공할 수 있게 준비하겠습니다.
<p class="error-description" th:text="${errorDescription ?: '잠시 후 다시 시도해 주세요.'}">
잠시 후 다시 시도해 주세요.
</p>
<!-- Error Message (서버에서 전달된 에러 메시지가 있을 경우 표시) -->
@@ -6,6 +6,10 @@
<meta content="https://www.eactive.co.kr/" property="og:url"/>
<meta charset="UTF-8"/>
<!-- CSRF 토큰 (세션 기반). 정적 JS/AJAX에서 토큰·헤더명을 읽어 사용한다. -->
<meta name="_csrf" th:content="${_csrf != null ? _csrf.token : ''}"/>
<meta name="_csrf_header" th:content="${_csrf != null ? _csrf.headerName : 'X-XSRF-TOKEN'}"/>
<meta content="max-age=0, public" http-equiv="Cache-Control"/>
<meta content="index, follow" name="robots"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
@@ -278,8 +278,15 @@
}
function csrfHeaders() {
var token = getCookie('XSRF-TOKEN');
return token ? { 'X-XSRF-TOKEN': token } : {};
// 세션 기반 CSRF: 쿠키 대신 <meta>에서 토큰·헤더명을 읽는다.
var tokenMeta = document.querySelector('meta[name="_csrf"]');
var headerMeta = document.querySelector('meta[name="_csrf_header"]');
var headers = {};
if (tokenMeta && tokenMeta.content) {
var headerName = (headerMeta && headerMeta.content) ? headerMeta.content : 'X-XSRF-TOKEN';
headers[headerName] = tokenMeta.content;
}
return headers;
}
function formatTime(sec) {