未找到预期的CSRF令牌。您的会话是否已过期403

时间:2015-01-25 16:49:52

标签: java spring

我正在尝试使用简单的示例编写我的测试弹簧安全应用程序。

Spring Security: 4.0.0.RC1
Spring: 4.1.4.RELEASE

我有以下安全配置:

<http auto-config="true">
    <intercept-url pattern="/admin**" 
                    access="hasRole('ADMIN')"/>
    <form-login authentication-failure-url="/?auth_error" 
                        username-parameter="user" 
                        password-parameter="password" 
                        login-page="/"
                        default-target-url="/?OK"/>
<!-- <csrf/> -->
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="mkyong" password="123456" authorities="ADMIN" />
        </user-service>
    </authentication-provider>
</authentication-manager>

登录页:

<html>
<body>
<form method="POST">
    <label for="user">User: </label>
    <input type="text" id="user" name="user" /> </br>
    <label for="password">Password: </label>
    <input type="text" name="password" id="password" /> </br>
    <input type="submit" /> 
</form>
</body>
</html>

现在,当我尝试登录时,我得到403错误页面:

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

描述:

Access to the specified resource (Invalid CSRF Token 'null' was
found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.) has been 
forbidden.

出了什么问题,我该如何解决这个问题?我在配置中评论了csrf,但错误消息与csrf有关。

5 个答案:

答案 0 :(得分:41)

我遇到了同样的问题。我使用thymeleaf和Spring启动,当我尝试在表单中发布数据时,我遇到了CSRF令牌问题。

这是我的工作解决方案:

  1. 添加此隐藏输入:

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

  2. WebSecurityConfig(扩展WebSecurityConfigurerAdapter)中,添加方法:

    private CsrfTokenRepository csrfTokenRepository() 
    { 
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); 
        repository.setSessionAttributeName("_csrf");
        return repository; 
    }
    

    并在方法configure()中添加代码:

    @Override
     protected void configure(HttpSecurity http) throws Exception {
         http.csrf()
         .csrfTokenRepository(csrfTokenRepository())
    
  3. 我花了很多时间在这个问题上。希望它可以帮助那些有同样问题的人。

答案 1 :(得分:24)

如果你必须禁用它......

在Spring Security 4中,CSRF is enabled by default使用XML配置时。以前,它仅在默认情况下启用基于Java的配置。

根据Section 14.4.2 of the Spring Security Documentation

  

从Spring Security 4.0开始,默认情况下使用XML配置启用CSRF保护。如果要禁用CSRF保护,可以在下面看到相应的XML配置。

<http>
   ...
   <csrf disabled="true"/>
   ...
</http>

答案 2 :(得分:20)

禁用CSRF保护听起来不错,不是吗?

如果您使用Spring的表单标记库,则会自动包含CSRF令牌。它还将HTML Escape表单元素值,这使您的网站对XSS更安全,更正确。

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> 

<form:form>
  <form:input...
</form:form>

否则,请将其添加到表单中:

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

答案 3 :(得分:4)

致@ St.Antario,   请使用此代码在代码中启用CSRF

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .antMatcher("*/*").authorizeRequests()
                .antMatchers("/", "/login**").permitAll()
                .anyRequest().authenticated()
                .and().csrf().csrfTokenRepository(csrfTokenRepository())
                .and().addFilterAfter(csrfHeaderFilter(), SessionManagementFilter.class);
    }

    private Filter csrfHeaderFilter() {
        return new OncePerRequestFilter() {

            @Override
            protected void doFilterInternal(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain filterChain) throws ServletException, IOException {

                CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
                if (csrf != null) {
                    Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                    String token = csrf.getToken();
                    if (cookie == null || token != null
                            && !token.equals(cookie.getValue())) {

                        // Token is being added to the XSRF-TOKEN cookie.
                        cookie = new Cookie("XSRF-TOKEN", token);
                        cookie.setPath("/");
                        response.addCookie(cookie);
                    }
                }
                filterChain.doFilter(request, response);
            }
        };
    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        //repository.setSessionAttributeName(("X-XSRF-TOKEN"));
        return repository;
    }
}

答案 4 :(得分:1)

您的登录页面叫什么名字 它以.jsp结尾

如果登录页面未以.jsp结尾,则Spring框架不会评估JSP或EL表达式