无法使用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上苦苦挣扎的人来说,这是我的步骤(虽然可以将其缩减很多,但是这些是解决该问题的高级概念):
实现Spring接口RequestDataValueProcessor并在Spring Security的XML配置中注册它,以便您可以重写方法getExtraHiddenFields,该方法允许您将隐藏的输入字段插入HTML(当然带有标记)。令牌本身是使用Java.Util UUID生成的。
使用JQuery,从该隐藏字段中读取值,然后设置请求标头的“ X-CSRF-Token”属性,以使其通过HTTP发送。无法将令牌仅保留在隐藏的输入字段中,因为我们没有执行表单Submit,而是使用AJAX POST来调用服务器端的方法。
扩展Spring的HandlerInterceptorAdapter并将其注册为拦截器,以便每次执行POST方法时,都会调用服务器端的“ preHandle”方法,以便可以将请求令牌(从上一步的HTTP标头中提取)与请求令牌进行比较。会话的令牌(应该相同!)。执行此检查后,它可以允许请求通过或返回错误。
以上是 无法使用Spring Security创建CSRF令牌 的全部内容, 来源链接: utcz.com/qa/413307.html