Spring Security:如何为Ajax安全控制过滤器正确配置CSRF

时间:2017-09-21 20:24:38

标签: spring spring-security

我正在使用Spring Security

该应用已启用以下内容:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/resources/css/**", "/resources/images/**", "/resources/jquery/**", "/resources/js/**").permitAll()
        ... more URLs to intercept  
        .antMatchers("/notification**").hasAuthority("ROLE_ADMIN")
        .antMatchers("/ajax/notification**").hasAuthority("ROLE_ADMIN")
        .anyRequest().authenticated()

        .and()
        .csrf()
        ...

观察CSRF已应用。对于表格,使用以下内容:

<c:url var="logoutUrl" value="/logout"/>
<form action="${logoutUrl}"
    method="post">
<input type="submit"
    value="Log out" />
<input type="hidden"
    name="${_csrf.parameterName}"
    value="${_csrf.token}"/>
</form>

根据Form Submissions

该应用程序运行良好如何预期,它会在加载/呈现jsp页面之前拦截任何URL并要求登录控制如何预期,如果用户已记录有关授权的控件应用如何预计也是。因此,所有人都在使用CSRF如何建议。

直到这里一切都好。

我在jQuery添加了ajax,因为它适用于网址,因此我也需要为该网址应用CSRF控件。

这就是上面出现的原因:

  • .antMatchers("/ajax/notification**").hasAuthority("ROLE_ADMIN")

现在,我希望在CSRF应用于ajax网址"/ajax/notification" 时获取预期的 HTTP错误代码和消息 CSRF标题发送。

js ajax代码是:

    $.getJSON(
            "/projectname-01/ajax/notification",  
            function(data, textStatus, req) {

                console.log("data: " + data);
                console.log("textStatus: " + textStatus);
                console.log("req: " + req)

                console.log("data: " + data);
                console.log(data.content + " " + data.date);

                $("#single").empty();
                $("#single").append(data.content + " " + data.date);

                $("#multiple").append(data.content + " " + data.date)
                              .append("<br/>");

            }
    )

注意:网址必须为/projectname-01/ajax/notificationprojectname-01是强制性的,如果删除,我会获得404。即使使用./ajax/notification它也不起作用(观察点)。

问题:代码工作正常,我的意思是,Ajax调用发生在服务器上没有任何问题,我期待一些错误,因为代码使用CRSF ajax的requeriments。

根据:

因此,例如:

<head>
    <meta name="_csrf" content="${_csrf.token}"/>
    <!-- default header name is X-CSRF-TOKEN -->
    <meta name="_csrf_header" content="${_csrf.headerName}"/>
    <!-- ... -->
</head>

<sec:csrfMetaTags />

当然js代码使用:

_csrf_parameter_csrf_header等。

然后,出于测试和生产目的,需要预期的HTTP错误代码和消息

因此,缺少什么?或者问题是什么?

标头:HTTP标头下方请求的方式:

来自Opera

General
  Request URL:http://localhost:8080/security-01/ajax/notification
  Request Method:GET
  Status Code:200 
  Remote Address:[::1]:8080
  Referrer Policy:no-referrer-when-downgrade
Response Headers
  HTTP/1.1 200
  X-Content-Type-Options: nosniff
  X-XSS-Protection: 1; mode=block
  Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  Pragma: no-cache
  Expires: 0
  X-Frame-Options: DENY
  Content-Type: application/json;charset=UTF-8
  Transfer-Encoding: chunked
  Date: Sat, 23 Sep 2017 00:14:20 GMT
Request Headers
  GET /security-01/ajax/notification HTTP/1.1
  Host: localhost:8080
  Connection: keep-alive
  Accept: application/json, text/javascript, */*; q=0.01
  X-Requested-With: XMLHttpRequest
  User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36 OPR/47.0.2631.80
  Referer: http://localhost:8080/security-01/tiles/notification/
  Accept-Encoding: gzip, deflate, br
  Accept-Language: en-US,en;q=0.8
  Cookie: JSESSIONID=9F2007DA3C8C683D26B8D17D85563140; jenkins-timestamper-offset=18000000

来自Firefox

Request Headers
  Host: localhost:8080
  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
  Accept: application/json, text/javascript, */*; q=0.01
  Accept-Language: en-US,en;q=0.5
  Accept-Encoding: gzip, deflate
  Referer: http://localhost:8080/security-01/tiles/notification/
  X-Requested-With: XMLHttpRequest
  Cookie: JSESSIONID=CF344E56DD03C4019DCA334CD38B73EC
  Connection: keep-alive

Response Header
  X-Content-Type-Options: nosniff
  X-XSS-Protection: 1; mode=block
  Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  Pragma: no-cache
  Expires: 0
  X-Frame-Options: DENY
  Content-Type: application/json;charset=UTF-8
  Transfer-Encoding: chunked
  Date: Sat, 23 Sep 2017 00:17:06 GMT

澄清

根据Spring Security Reference Documentation,我们对CSRF的{​​{1}}页面(提交表单)申请JSP,同时使用Ajax {1}}。对于前者我已经配置并且工作正常。后者是问题。

当我使用URL&#39; jQuery来电而不时,会发送特殊的$.getJSONCSRF data/headers,{{1} }等等,我的意思是:30.6 The csrfMetaTags Tag出现如下:

<sec:csrfMetaTags />

从上方发送来自meta[name='_csrf_parameter'] // using JQuery to send an x-www-form-urlencoded request var data = {}; data[csrfParameter] = csrfToken; data["name"] = "John"; ... $.ajax({ url: "http://www.example.org/do/something", type: "POST", data: data, ... }); // using JQuery to send a non-x-www-form-urlencoded request var headers = {}; headers[csrfHeader] = csrfToken; $.ajax({ url: "http://www.example.org/do/something", type: "POST", headers: headers, ... }); 的{​​{1}}信息。但在我的代码中,我发送它。因此,我希望通过CRSF

报告一些特殊控制和错误

因此,使用我当前的ajax代码,通过在运行时开发(data与app一起运行),对服务器的调用发生并返回数据。因此headers没有拦截并因这些Spring Security缺席而引发错误。

因此,现在考虑进行开发和测试,如果我创建的Tomcat方法应该失败,因为Spring Security发送。 CRSF data/headers方法将失败,因为调用服务器时没有任何安全性控件。

1 个答案:

答案 0 :(得分:1)

您的HTTP GET请求不会产生任何错误,因为只有更新状态的请求才需要CSRF令牌,请参阅Spring Security Reference

  

18.2同步器令牌模式

     

[...]
  我们可以放松期望,只需要更新状态的每个HTTP请求的令牌。这可以安全地完成,因为相同的原始策略确保恶意站点无法读取响应。此外,我们不希望在HTTP GET中包含随机令牌,因为这会导致令牌泄露。

CsrfFilter

  

使用同步器令牌模式应用CSRF保护。开发人员必须确保为允许状态更改的任何请求调用CsrfFilter。通常这只意味着他们应该确保他们的Web应用程序遵循正确的REST语义(即不要使用HTTP方法GET,HEAD,TRACE,OPTIONS来改变状态。)

要获取CSRF令牌,您必须使用HTTP POSTPUTDELETE请求。