【问题标题】:Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'在请求参数“_csrf”或标头“X-CSRF-TOKEN”上发现无效的 CSRF 令牌“null”
【发布时间】:2014-02-03 08:51:44
【问题描述】:

配置 Spring Security 3.2 后,_csrf.token 未绑定请求或会话对象。

这是 Spring Security 配置:

<http pattern="/login.jsp" security="none"/>

<http>
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <form-login login-page="/login.jsp"
                authentication-failure-url="/login.jsp?error=1"
                default-target-url="/index.jsp"/>
    <logout/>
    <csrf />
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="test" password="test" authorities="ROLE_USER/>
        </user-service>
    </authentication-provider>
</authentication-manager>

login.jsp 文件

<form name="f" action="${contextPath}/j_spring_security_check" method="post" >
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    <button id="ingresarButton"
            name="submit"
            type="submit"
            class="right"
            style="margin-right: 10px;">Ingresar</button>
    <span>
        <label for="usuario">Usuario :</label>
        <input type="text" name="j_username" id="u" class="" value=''/>
    </span>
    <span>
        <label for="clave">Contrase&ntilde;a :</label>

        <input type="password"
               name="j_password"
               id="p"
               class=""
               onfocus="vc_psfocus = 1;"
               value="">
    </span>
</form>

它会渲染下一个 html:

<input type="hidden" name="" value="" />

结果是 403 HTTP 状态:

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

更新 经过一些调试,请求对象从 DelegatingFilterProxy 中得到了很好的结果,但是在 CoyoteAdapter 的第 469 行它执行了 request.recycle();删除所有属性...

我在 Tomcat 6.0.36、7.0.50 和 JDK 1.7 中进行测试。

我不理解这种行为,而不是,如果有人指出我与 Spring Security 3.2 与 CSRF 一起使用的一些应用程序示例战争的方向,那将是可能的。

【问题讨论】:

  • 你使用什么 Spring 版本?这同样适用于我(但在 spring-security.xml 中存在差异)与 Spring 4.0.0 RELEASE (GA)、Spring Security 3.2.0 RELEASE (GA)(尽管它与 Struts 2.3.16 集成。我没有单独使用 Spring MVC 试试)。但是,当请求 multipart 用于上传状态为 403 的文件时,它会失败。我正在努力寻找解决方案。
  • Spring 3.2.6,Spring Security 3.2.0,CSRF,token被添加到http-request对象中,session对象和请求线程一样,但是出去的时候直到它渲染 jsp 删除所有属性,只留下一个属性 ...filter_applied
  • @Tiny:你有没有找到解决多部分问题的方法?我遇到了 exact 同样的问题。
  • @AlienBishop :是的,请查看this 答案(它使用了 Spring 和 Struts 的组合)。如果您只有 Spring MVC,请查看 this 答案。需要注意的是,web.xml 中过滤器的顺序至关重要。 MultipartFilter 必须在 springSecurityFilterChain 之前声明。希望有帮助。谢谢。

标签: spring spring-security csrf csrf-protection


【解决方案1】:

您的 Spring 应用程序中的 CSRF(跨站点请求伪造)保护似乎已启用。实际上它是默认启用的。

根据spring.io

什么时候应该使用 CSRF 保护?我们的建议是使用 CSRF 保护可以由浏览器处理的任何请求 普通用户。如果您只创建一个由 非浏览器客户端,您可能希望禁用 CSRF 保护。

所以要禁用它:

@Configuration
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
  }
}

如果您想保持启用 CSRF 保护,那么您必须在表单中包含csrftoken。你可以这样做:

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

您甚至可以在表单的操作中包含 CSRF 令牌:

<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">

【讨论】:

  • 这应该被接受为答案,因为它不仅说明了要做什么,而且说明了在采取措施阻止这些错误之前应该考虑的事项。
  • 你也可以.csrf().ignoringAntMatchers("/h2-console/**")
  • 在上面的答案中避免使用查询参数样式。如果你这样做,你就是在公开暴露代币。
【解决方案2】:

你不应该添加到登录表单吗?;

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

如 Spring 安全文档中的 here 所述

【讨论】:

    【解决方案3】:

    如果您申请security="none",则不会生成 csrf 令牌。该页面不会通过安全过滤器。使用角色 ANONYMOUS。

    我没有详细介绍,但它对我有用。

     <http auto-config="true" use-expressions="true">
       <intercept-url pattern="/login.jsp" access="hasRole('ANONYMOUS')" />
       <!-- you configuration -->
       </http>
    

    【讨论】:

    • 我使用 security=none 并转向您的答案解决了这个问题。 thymeleaf 自动添加 csrf 令牌真是太棒了。谢谢!
    【解决方案4】:

    尝试将这个:&lt;csrf /&gt; 更改为这个:&lt;csrf disabled="true"/&gt;。它应该禁用 csfr。

    【讨论】:

      【解决方案5】:

      你可以用百里香添加:

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

      【讨论】:

        【解决方案6】:

        禁用 csrf 的 Spring 文档:https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-configure

        @EnableWebSecurity
        public class WebSecurityConfig extends
        WebSecurityConfigurerAdapter {
        
           @Override
           protected void configure(HttpSecurity http) throws Exception {
              http.csrf().disable();
           }
        }
        

        【讨论】:

        • 请不要复制现有答案。
        【解决方案7】:

        我以前也有同样的问题。

        您的配置使用 security="none" 因此无法生成 _csrf:

        <http pattern="/login.jsp" security="none"/>
        

        你可以为页面/login.jsp设置access="IS_AUTHENTICATED_ANONYMOUSLY"替换上面的配置:

        <http>
            <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
            <intercept-url pattern="/**" access="ROLE_USER"/>
            <form-login login-page="/login.jsp"
                    authentication-failure-url="/login.jsp?error=1"
                    default-target-url="/index.jsp"/>
            <logout/>
            <csrf />
        </http>
        

        【讨论】:

          【解决方案8】:

          我认为 csrf 只适用于 spring 表单

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

          更改为form:form 标签并查看它是否有效。

          【讨论】:

          【解决方案9】:

          请查看我的工作示例应用程序on Github 并与您的设置进行比较。

          【讨论】:

          • 我将降级到 spring 3.2.6,我希望它可以在没有 spring mvc 的情况下工作。
          • 是的,它应该可以正常工作,因为我使用 Spring 3.1.4 上的现有应用程序创建了示例应用程序。
          • 哈哈哈哈哈,太好了,让它工作只是降级不是解决方案 bhaiya ji @manish
          【解决方案10】:

          这两种解决方案都不适合我。唯一对我有用的 Spring 形式是:

          action="./upload?${_csrf.parameterName}=${_csrf.token}"

          替换为:

          action="./upload?_csrf=${_csrf.token}"

          (Spring 5 在 java 配置中启用了 csrf)

          【讨论】:

            【解决方案11】:

            在您的控制器中添加以下内容:

            @RequestParam(value = "_csrf", required = false) String csrf
            

            并在jsp页面上添加

            <form:form modelAttribute="someName" action="someURI?${_csrf.parameterName}=${_csrf.token}
            

            【讨论】:

              猜你喜欢
              • 2018-03-16
              • 2015-09-03
              • 2015-11-16
              • 2016-09-11
              • 2019-02-03
              • 2015-11-05
              • 2021-03-18
              • 2016-03-29
              • 2016-10-03
              相关资源
              最近更新 更多