无法使用Spring Security创建CSRF令牌

我在Spring MVC应用程序中使用Spring Security 3.2.3,并且出现了一些意外的行为。

根据此处的文档,应该可以${_csrf.token}在我的html的meta标签中使用:

<meta name="_csrf" content="${_csrf.token}" />

<!-- default header name is X-CSRF-TOKEN -->

<meta name="_csrf_header" content="${_csrf.headerName}" />

我从此处使用JQuery提取“内容”的值,然后使用AJAX将其放入“请求标头”中。

但是由于某种原因,Spring Security不会将其“转换”为实际的令牌,而只是以文字字符串“ $ {_ csrf.token}”的形式发送到标头中。

${_csrf.token}根据文档,尝试使用隐藏输入的替代方法,然后我尝试通过检查输入的值来检查令牌的计算结果,但它仍然只是纯文本“ $ {_

csrf.token}”。

由于似乎Spring Security无效,我是否缺少某种配置?我目前正在使用准系统Spring Security Java配置(而不是xml),如下所示:

import org.springframework.context.annotation.*;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.*;

@Configuration

@EnableWebSecurity

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override

protected void configure(HttpSecurity http) throws Exception {

http

.csrf();

}

}

我知道configure会被调用,因为我在其中放置了一条调试语句,因此我认为CSRF保护确实已启用,因为默认情况下应该启用它。

我意识到语法“ $ {}”是JSP表达式语言,并且我目前正在成功地使用它来将上下文评估为Thymeleaf对象,例如:

th:object="${context}"

因此,我尝试在meta标签的“内容”前面添加“ th:”,如下所示:

<meta name="_csrf" th:content="${_csrf.token}"/>

但这会导致无法评估的异常:

评估SpringEL表达式的异常:“ _ csrf.token”

我认为这里的关键可能是弄清楚如何使该表达式在我看来正确评估。

回答:

我终于解决了这个问题,但是它基本上需要重写Spring Security。这就是它的全部荣耀。

首先,我遵循了Eyal Lupu 在此处的精彩博客文章中的建议,但是由于我的AJAX要求,我不得不根据自己的情况进行调整。

至于Thymeleaf的情况,关键花絮隐藏在Thymeleaf论坛的档案中-臭名昭著的第7期。

https://github.com/thymeleaf/thymeleaf-

spring/issues/7#issuecomment-27643488

Thymeleaf的创建者本人最后的评论是:

th:action…检测何时将此属性应用到标记上(无论如何应该是唯一的位置),并且在这种情况下调用RequestDataValueProcessor.getExtraHiddenFields(…),并在结束标记之前添加返回的隐藏字段。

那是我需要令牌才能工作的关键词。不幸的是,为什么th:action也要启动尚不完全清楚getExtraHiddenFields,但是无论如何它确实很重要。

因此,对于任何在Thymeleaf + Spring Security CSRF + AJAX

POST上苦苦挣扎的人来说,这是我的步骤(虽然可以将其缩减很多,但是这些是解决该问题的高级概念):

  1. 实现Spring接口RequestDataValueProcessor并在Spring Security的XML配置中注册它,以便您可以重写方法getExtraHiddenFields,该方法允许您将隐藏的输入字段插入HTML(当然带有标记)。令牌本身是使用Java.Util UUID生成的。

  2. 使用JQuery,从该隐藏字段中读取值,然后设置请求标头的“ X-CSRF-Token”属性,以使其通过HTTP发送。无法将令牌仅保留在隐藏的输入字段中,因为我们没有执行表单Submit,而是使用AJAX POST来调用服务器端的方法。

  3. 扩展Spring的HandlerInterceptorAdapter并将其注册为拦截器,以便每次执行POST方法时,都会调用服务器端的“ preHandle”方法,以便可以将请求令牌(从上一步的HTTP标头中提取)与请求令牌进行比较。会话的令牌(应该相同!)。执行此检查后,它可以允许请求通过或返回错误。

以上是 无法使用Spring Security创建CSRF令牌 的全部内容, 来源链接: utcz.com/qa/413307.html

回到顶部