티스토리 뷰
나의 작업에서 아래의 원인이 아닌 듯.. <form:form> 두개 사용하고 있는 page 발견.. 더 알아봐야 함.
✅ JSP에서 <form:form>을 2번 사용했더니 CSRF 토큰이 포함되지 않는 이유
전자정부프레임워크(Spring Security 기반)에서는 JSP에서 <form:form>을 사용할 경우 CSRF 토큰을 자동 추가합니다.
하지만 JSP 내에서 <form:form>을 2번 이상 사용하면 CSRF 토큰이 한 번만 포함되거나, 일부 <form>에서 누락될 수 있는 문제가 발생할 수 있습니다.
🔹 1️⃣ CSRF 토큰이 자동으로 추가되지 않는 원인
JSP에서 <form:form>을 여러 번 사용했을 때 CSRF 토큰이 포함되지 않는 주된 원인은 다음과 같습니다.
✅ 원인 1: CsrfRequestDataValueProcessor가 한 번만 실행됨
- Spring Security의 CsrfRequestDataValueProcessor는 페이지에서 한 번만 동작하도록 설계됨
- 첫 번째 <form:form>에서는 CSRF 토큰이 정상적으로 포함되지만, 두 번째 <form:form>부터는 자동 추가되지 않을 가능성이 있음
✅ 원인 2: 같은 JSP 페이지 내에서 여러 개의 <form:form>이 렌더링될 때 중복 처리 문제
- <form:form> 태그는 내부적으로 Spring Form Tag Library를 사용하여 CSRF 토큰을 추가함
- 하지만 Spring이 CSRF 토큰을 삽입할 때 첫 번째 폼에만 자동으로 추가하고, 이후 폼에는 추가되지 않을 수 있음
🔹 2️⃣ 해결 방법
✅ 해결 방법 1: sec:csrfInput을 명시적으로 추가
Spring Security의 <sec:csrfInput/> 태그를 사용하여 CSRF 토큰을 강제로 포함할 수 있습니다.
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
✔ 각 <form:form> 태그 내부에 <sec:csrfInput/>을 추가하면 CSRF 토큰이 정상적으로 포함됨
✅ 해결 방법 2: hidden input을 직접 추가하기
CSRF 토큰을 hidden input으로 강제로 삽입하면 여러 개의 <form>에서도 정상적으로 동작합니다.
<form:form modelAttribute="form1" action="/submitForm1" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<form:input path="name"/>
<input type="submit" value="제출">
</form:form>
<form:form modelAttribute="form2" action="/submitForm2" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<form:input path="email"/>
<input type="submit" value="제출">
</form:form>
✔ 각 <form>에 CSRF 토큰을 수동으로 추가하면 여러 개의 폼에서도 정상적으로 작동함
✅ 해결 방법 3: spring-security-taglibs를 활용하여 CSRF 메타 태그 추가
JSP에서 CSRF 토큰을 <meta> 태그로 추가하고, JavaScript를 활용하여 각 <form>에 CSRF 토큰을 삽입하는 방법도 있습니다.
(1) JSP에 CSRF 토큰을 <meta> 태그로 추가
<sec:csrfMetaTags/>
✔ 위 태그를 추가하면, 자동으로 다음과 같은 <meta> 태그가 생성됨
<meta name="_csrf" content="abc123"/>
<meta name="_csrf_header" content="X-CSRF-TOKEN"/>
(2) JavaScript로 CSRF 토큰을 모든 <form>에 추가
$(document).ready(function() {
var csrfToken = $("meta[name='_csrf']").attr("content");
var csrfParam = $("meta[name='_csrf_header']").attr("content");
$("form").each(function() {
$(this).append('<input type="hidden" name="' + csrfParam + '" value="' + csrfToken + '"/>');
});
});
✔ 이렇게 하면 모든 <form>에 CSRF 토큰이 자동으로 삽입됨
🔹 3️⃣ 최종 정리
해결 방법 설명 추천 여부
<sec:csrfInput/> 추가 | 각 <form:form> 태그에 CSRF 토큰을 명시적으로 추가 | ✅ (권장) |
hidden input 수동 추가 | ${_csrf.token}을 사용하여 직접 추가 | ✅ (권장) |
sec:csrfMetaTags + JavaScript | <meta> 태그 활용 후 모든 <form>에 JavaScript로 CSRF 토큰 추가 | ⚠️ (상황에 따라 사용 가능) |
💡 결론
📌 JSP에서 <form:form>을 여러 개 사용하면 CSRF 토큰이 한 번만 자동 추가되는 경우가 있음
📌 이 문제를 해결하려면 <sec:csrfInput/>을 명시적으로 추가하거나 hidden input을 직접 삽입하는 것이 가장 확실한 방법
📌 AJAX 요청을 고려해야 한다면 <sec:csrfMetaTags/>를 활용하여 JavaScript로 처리하는 것도 가능 🚀
- Total
- Today
- Yesterday
- $.each
- setter
- caniuse
- object key
- 프로젝트명변경
- ul li로 테이블
- Javascript
- PostgreSQL
- DatePicker
- 진열사랑
- spring
- 여러 컬럼 update
- springboot
- 정규식
- JQuery
- sumifs
- draw.io
- Keycode
- CSS
- @ExceptionHandler
- 전후방탐색
- element위치
- border-collapse
- lombok
- oracle
- getter
- QueryDSL
- devtools
- excel
- $.extend
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |