Spring Security CSRF 令牌不适用于 AJAX

Posted

技术标签:

【中文标题】Spring Security CSRF 令牌不适用于 AJAX【英文标题】:Spring Security CSRF Token not working with AJAX 【发布时间】:2015-03-06 06:10:30 【问题描述】:

我的 Spring Boot 应用程序中的 csrf 令牌有问题。

我有一个可以编辑人员的表单。一个人可以拥有

现在让我们假设这个人有一辆车,然后进入并存储它。下次他要删除这辆车并进入另一辆车。我已经创建了这个列表,以便列出他所有的汽车——他可以选择从列表中删除它。现在我从这些药丸开始,想用相应的 ID 向服务器发送一个 POST。当我尝试时,我得到了 403 禁止,我不知道为什么。

如果我从 POST 更改为 GET,那么它可以工作。

我的 javascript(取自本网站:http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag)

var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
var csrfHeader = $("meta[name='_csrf_header']").attr("content");
var csrfToken = $("meta[name='_csrf']").attr("content");

// using JQuery to send a non-x-www-form-urlencoded request
var headers = ;
headers[csrfHeader] = csrfToken;
$.ajax(
    url: "./delete/car",
    type: "GET",
    headers: headers,
);

$.ajax(
     url: "./delete/car",
     type: "POST",
     headers: headers,
);

我的控制器方法:

@RequestMapping(value = "/login/delete/car", method = RequestMethod.GET)
    public ModelAndView delete(@PathVariable("login") final String login) 
        System.out.println("Stop");
        return new ModelAndView("redirect:" + WebSecurityConfig.URL_PERSONS_OVERVIEW);
    

    @RequestMapping(value = "/login/delete/car", method = RequestMethod.POST)
    public ModelAndView deleteInstEmp(@PathVariable("login") final String login) 
        System.out.println("Stop");
        return new ModelAndView("redirect:" + WebSecurityConfig.URL_PERSONS_OVERVIEW);
    

有什么建议吗?

提前致谢。

【问题讨论】:

"/login/delete/car", method = RequestMethod.GET 这个监听 GET 请求而不是 POST 抱歉,从我的网站复制粘贴错误。在我看来是对的 【参考方案1】:

好的,经过所有这些努力,我得到了以下结果。

我在 Ajax 构造中添加了fail 方法并得到以下消息:

“无法对 'XMLHttpRequest' 执行 'setRequestHeader':'$_csrf.headerName' 不是有效的 HTTP 标头字段名称。”

spring 官方网站建议你必须把这个:<sec:csrfMetaTags /> 或其他来源的这个:<meta name="_csrf" th:content="$_csrf.token"/> 放在你的 html 文件中。

在此之后,您应该能够在 JavaScript 中访问这些属性,但在我的例子中,我得到了 undefined$_csrf.headerName

最后一次尝试是从隐藏值中获取值(第 24.5 章:http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag)。

现在,我有以下内容:

$(function () 
    var token = $("input[name='_csrf']").val();
    var header = "X-CSRF-TOKEN";
    $(document).ajaxSend(function(e, xhr, options) 
        xhr.setRequestHeader(header, token);
    );
);

$.ajax(
    url: "./delete/car",
    type: "POST",
    success:function(response) 
        alert(response);
    
);

有了它,它就像一个魅力。

【讨论】:

完美!!我什至在徘徊如何表达它。有用。谢谢!【参考方案2】:

另外一种方式,你可以使用下面的代码:

$.ajax(
    url : './delete/car',
    headers: "X-CSRF-TOKEN": $("input[name='_csrf']").val(),
    type : 'POST',
    success : function(result) 
        alert(result.msgDetail);
    
)

【讨论】:

【参考方案3】:

    我建议您首先检查是否使用 chrome 调试器生成了有效的 csrf 令牌和标头。如果没有,那么您是否在<head> 中添加了<sec:csrfMetaTags />?(您需要导入spring 安全标签库)。如果使用 Apache 切片,则必须将其添加到用于视图的模板文件的 <head> 部分。

    如果令牌不为空,则在您的安全上下文/配置文件中,检查您是否已禁用 csrf 安全性。默认情况下,它已启用,并且需要此进程才能正常工作。

【讨论】:

以上是关于Spring Security CSRF 令牌不适用于 AJAX的主要内容,如果未能解决你的问题,请参考以下文章

在 spring-security 中更改 csrf 令牌

Spring Security 未创建 CSRF 令牌

使用 Spring Security 重命名 CSRF 令牌头名称

无法使用 Spring Security 创建 CSRF 令牌

Spring security中每个请求的不同csrf令牌

Spring Security - CSRF - 如何重置 CSRF 令牌并记录潜在的 CSRF 攻击(OWASP 推荐)