spring 找不到预期的CSRF令牌,您的会话是否已过期403

eiee3dmh  于 2023-03-28  发布在  Spring
关注(0)|答案(7)|浏览(135)

我正在尝试使用mkyong示例编写Spring Security 测试应用程序。

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有关。

hec6srdp

hec6srdp1#

我也遇到了同样的问题。我使用Thymeleaf和Sping Boot ,当我试图在表单中发布数据时,遇到了CSRF令牌问题。
以下是我的工作解决方案:
1.添加此隐藏输入:
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
1.在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())

我花了很多时间在这个问题上。希望它能帮助有同样问题的人。

os8fio9y

os8fio9y2#

如果你一定要禁用它...
在Spring Security 4中,当使用XML配置时,CSRF is enabled by default。以前它只在基于Java的配置中默认启用。
根据Spring Security文档的第14.4.2节:
从Spring Security 4.0开始,CSRF保护默认通过XML配置启用。如果您想禁用CSRF保护,可以在下面看到相应的XML配置。

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

xvw2m8pv3#

禁用CSRF保护听起来是个坏主意,不是吗?
如果你使用Spring的Form Tag库,CSRF令牌将被自动包含。它还将HTML转义表单元素值,这使你的站点对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}"/>
ne5o7dgx

ne5o7dgx4#

收件人:@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;
    }
}
oxcyiej7

oxcyiej75#

spring-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xsi:schemaLocation="
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security.xsd
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <http pattern="/resources/**" security="none" />

    <http use-expressions="true">
        <intercept-url pattern="/login*" access="isAnonymous()" />
        <intercept-url pattern="/**" access="isAuthenticated()"/>
        <form-login
            login-page="/login"
            default-target-url="/home"
            authentication-failure-url="/login?error=true" /> 
        <logout
            logout-success-url="/login"
            delete-cookies="JSESSIONID" />
    </http>
    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="carlos" password="123" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
</beans:beans>

web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml, /WEB-INF/spring-security.xml</param-value>
</context-param>

添加添加jsp登录

<%@page session="true"%>

并隐藏输入:

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

nhn9ugyo6#

您的登录页面名是什么?是否以.jsp结尾
如果登录页面不是以.jsp结尾,Spring框架就不会计算JSP或EL表达式

dgsult0t

dgsult0t7#

问题:

在Sping Boot 2.7中,csrf默认为DISABLED
在Sping Boot 3.x中,csrf默认为ENABLED
溶液

@EnableWebFluxSecurity
@Configuration
public class ReactiveWebfluxSecurityConfig {

  @Bean
  public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http.csrf(ServerHttpSecurity.CsrfSpec::disable);
    return http.build();
  }
}
备注

不要忘记要像在Spring 3.0中那样将@Configuration添加到@EnableWebFluxSecurity,必须像我在上面的代码片段中所做的那样显式添加。

相关问题