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

St.*_*rio 27 java spring

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

Spring Security: 4.0.0.RC1
Spring: 4.1.4.RELEASE
Run Code Online (Sandbox Code Playgroud)

我有以下安全配置:

<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>
Run Code Online (Sandbox Code Playgroud)

登录页面:

<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>
Run Code Online (Sandbox Code Playgroud)

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

Invalid CSRF Token 'null' was found on the request parameter 
'_csrf' or header 'X-CSRF-TOKEN'.
Run Code Online (Sandbox Code Playgroud)

描述:

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

怎么了,怎么解决这个问题?我csrf在配置中注释,但错误消息与csrf.

小智 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; 
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

    @Override
     protected void configure(HttpSecurity http) throws Exception {
         http.csrf()
         .csrfTokenRepository(csrfTokenRepository())
    
    Run Code Online (Sandbox Code Playgroud)

我花了很多时间在这个问题上.希望它可以帮助那些有同样问题的人.


Tod*_*odd 24

如果你必须禁用它...

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

根据Spring Security文档的第14.4.2节:

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

<http>
   ...
   <csrf disabled="true"/>
   ...
</http>
Run Code Online (Sandbox Code Playgroud)

  • 有意思,但如果我想使用csrf,我怎么能提供有效的csrf令牌呢?可能吗? (7认同)

Nei*_*gan 20

禁用CSRF保护听起来像个坏主意,不是吗?

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

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

<form:form>
  <form:input...
</form:form>
Run Code Online (Sandbox Code Playgroud)

否则,将其添加到您的表单:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
Run Code Online (Sandbox Code Playgroud)


Jav*_*hin 5

致@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;
    }
}
Run Code Online (Sandbox Code Playgroud)