Why does my spring security configuration seem to reject a valid csrf token

I studied Spring Security (and interface development) with a few tutorials. However, I am very confused by CSRF tokens, and I am clearly doing something wrong.

My Spring Security is configured using java, and when I disable CSRF (using the following snippet), the form submits without problems.

 http.csrf().disable();

My understanding from here is that the steps I need to follow are as follows:

    1) Use proper verbs 
    2) Enable csrf protection
    3) include _csrf as hidden fields in form.  

All these steps sound simple, but they don't seem to work for me, and I get an error:

HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

when I try to submit my registration form.

, "_csrf" . , , , , , .

:

        <form method="POST" th:object="${individualRegistrationInfo}">
            <table>
                <tr>
                    <td>Name:</td>
                    <td><input type="text" th:field="*{name}" /></td>
                    <td th:if="${#fields.hasErrors('name')}"><p th:errors="*{name}">Incorrect Name</p></td>
                </tr>

                <tr>
                    <td>Username:</td>
                    <td><input type="text" th:field="*{username}" /></td>
                    <td th:if="${#fields.hasErrors('username')}"><p th:errors="*{username}">Incorrect Username</p></td>
                </tr>
                <tr>
                    <td>Password:</td>
                    <td><input type="password" th:field="*{password}" /></td>
                    <td th:if="${#fields.hasErrors('password')}"><p th:errors="*{password}">Incorrect Password</p></td>
                </tr>
                <tr>
                    <td>Email:</td>
                    <td><input type="email" th:field="*{email}" /></td>
                    <td th:if="${#fields.hasErrors('email')}"><p th:errors="*{email}">Incorrect Email</p></td>
                </tr>

                <tr>
                    <td>Confirm Email:</td>
                    <td><input type="email" th:field="*{confirmEmail}" /></td>
                    <td th:if="${#fields.hasErrors('confirmEmail')}"><p th:errors="*{confirmEmail}">Incorrect Email Confirmation</p></td>
                </tr>  
                <tr>
                    <td>Region:</td>
                    <td><select th:field="*{regionName}">
                    <option value="NONE">----Select----</option>
                      <option th:each="region : ${regions}" th:value="${region}" th:text="${region}">RegionTemplate</option>    
                    </select></td>
                    <td th:if="${#fields.hasErrors('regionName')}"><p th:errors="*{regionName}">Region Name</p></td>
                </tr> 
                <tr><td>
                <span th:text= "${_csrf.parameterName}">CSRF Parm Name</span></td>
               <td> <span th:text= "${_csrf.token}">CSRF Token value</span> </td></tr>
                <tr>
                    <td colspan="3">
                        <input type="submit" value="Register" />
                    </td>
                </tr>
                  <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
            </table>
        </form>

, , : " , CSRF HttpSession, , HttpSession, AccessDeniedHandler InvalidCsrfTokenException. AccessDeniedHandler , HTTP 403 ".

HttpSession, , - ( ). , , , - .

gradle:

compile group: 'org.springframework', name: 'spring-webmvc', version:'4.0.5.RELEASE'
compile group: 'org.springframework', name: 'spring-context-support', version:'4.0.5.RELEASE'

compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version:'1.1.4.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf', version:'1.1.4.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-security', version:'1.1.4.RELEASE'
testCompile group: 'org.springframework.security', name:'spring-security-test', version:'4.0.0.M1'

, :

    1) Use proper verbs (POST is clearly visible on the form code snippet)
    2) Enable csrf protection (http.csrf().disable(); is commented out and _CSRF shows in form)
    3) include _csrf as hidden fields in form. (clearly visible on the form code snippet) 

, ,

    4) I am missing something ! 

- , ?

, , .

29

, CSRF.

, AccessDeniedHandler, .

. , _csrf, , AccessDeniedHandler.

:

    static class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)
            throws IOException, ServletException {

        logger.warn("Arrived in custom access denied handler.");
        HttpSession session = request.getSession();
        System.out.println("Session is " +session );
        System.out.println("Session id = " + session.getId());
        System.out.println("Session max interval="+session.getMaxInactiveInterval());
        System.out.println("Session last used="+session.getLastAccessedTime());
        System.out.println("Time now="+new Date().getTime());

        System.out.println();
        System.out.println("csrf:");
        Object csrf = request.getAttribute("_csrf");

        if (csrf==null) { 
            System.out.println("csrf is null");
        } else { 
            System.out.println(csrf.toString());
            if (csrf instanceof DefaultCsrfToken) { 
                DefaultCsrfToken token = (DefaultCsrfToken) csrf;
                System.out.println("Parm name " + token.getParameterName());
                System.out.println("Token " + token.getToken());
            }

        }
        System.out.println();
        System.out.println("Request:");
        System.out.println(request.toString());
        System.out.println();
        System.out.println("Response:");
        System.out.println(response.toString());
        System.out.println();
        System.out.println("Exception:");
        System.out.println(accessDeniedException.toString());
    }
}

:

Session is org.apache.catalina.session.StandardSessionFacade@579ebbb8
Session id = 7CC03DAFF6BC34E28F5E91974C7E4BA5
Session max interval=1800
Session last used=1406630832436
Time now=1406630878254

csrf:
org.springframework.security.web.csrf.DefaultCsrfToken@763659f8
Parm name _csrf
Token 1e9cb3cf-c111-4b05-aace-4f8480b7d67b

Request:
   org.springframework.security.web.context.HttpSessionSecurityContextRepository$Servlet3SaveToSessionRequestWrapper@6a4ce569

Response:
    org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper@5e698704

Exception:
org.springframework.security.web.csrf.InvalidCsrfTokenException: Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

1e9cb3cf-c111-4b05-aace-4f8480b7d67b .

, CSRF "null", , "_csrf".

30 , GitHub: https://github.com/Mark-Allen/csrf-example.git

. 52 SecurityWebConfiguration (. , ), .

 http.csrf().disable();

@Bart, , .

, - , .

+4
2

, - ( ), .

, , Thymeleaf.

Thymeleaf Spring (http://www.thymeleaf.org/doc/springsecurity.html), , "th: action" "action" . .

, "th: action", Thymeleaf , "" csrf.

+3

, , , . _csrf.

<input type="hidden" name="_csrf" value="${_csrf.token}"/>
0

All Articles