티스토리 뷰

나의 작업에서 아래의 원인이 아닌 듯.. <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
링크
«   2025/04   »
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
글 보관함