SpringSecurity框架下实现CSRF跨站攻击防护

file

1、什么是CSRF

不少朋友在学习Spring Security的时候,会将CORS(跨站资源共享)和CSRF(跨站请求伪造)弄混,觉得两者是一回事。其实不是,先解释一下:前端

  • CORS(跨站资源共享)是局部打破同源策略的限制,使在必定规则下HTTP请求能够突破浏览器限制,实现跨站访问。
  • CSRF是一种网络攻击方式,也能够说是一种安全漏洞,这种安全漏洞在web开发中普遍存在。

当咱们使用Spring Security的时候,这种CSRF漏洞默认的被防护掉了。可是你会发如今跨域请求的状况下,咱们的POST、DELETE、PUT等HTTP请求方式失效了。因此在笔者以前的文章中,咱们使用http.csrf.disable()暂时关闭掉了CSRF的防护功能,可是这样是不安全的,那么怎么样才是正确的作法呢?就是本文须要向你们介绍的内容。web

2、CSRF的攻击方式

一般的CSRF攻击方式以下:ajax

  • 你登陆了网站A,攻击者向你的网站A帐户发送留言、伪造嵌入页面,带有危险操做连接。
  • 当你在登陆状态下点击了攻击者的链接,所以该连接对你网站A的帐户进行了操做。
  • 这个操做是你在网站A中主动发出的,而且也是针对网站A的HTTP连接请求,同源策略没法限制该请求。

3、如何防护CSRF攻击

  • 为系统中的每个链接请求加上一个token,这个token是随机的,服务端对该token进行验证。破坏者在留言或者伪造嵌入页面的时候,没法预先判断CSRF token的值是什么,因此当服务端校验CSRF token的时候也就没法经过。因此这种方法在必定程度上是靠谱的。
  • 可是若是你的电脑中毒,网络信息被劫持使用token的方法仍然不安全。因此没有绝对的安全,道高一次魔高一丈。做为开发者,咱们就作到咱们应该作到的。
  • 跳转提示:当用户不当心点击了第三方链接,合格的应用应该提示用户相关的风险!由用户本身确认是否真的要跳转或者执行第三方链接,或者就干脆不让非可信链接在留言区等地方存在。

4、Spring Security的CSRF token攻击防御

首先,咱们要先开启防御功能,在用户登录操做以后,生成的CSRF Token就保存在cookies中。spring

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .ignoringAntMatchers("/authentication");
        .and()
        ...
    }
}复制代码
  • 使用CookieCsrfTokenRepository生成CSRF Token放入cookie,并设置cookie的HttpOnly=false,容许js读取该cookie。
  • 使用ignoringAntMatchers开放一些不须要进行CSRF防御的访问路径,好比:登陆受权。

至此,咱们生成了CSRF token保存在了cookies中,浏览器向服务端发送的HTTP请求,都要将CSRF token带上,服务端校验经过才能正确的响应。这个校验的过程并不须要咱们本身写代码实现,Spring Security会自动处理。可是咱们须要关注前端代码,如何正确的携带CSRF token。后端

5、前端请求携带CSRF Token的方式

在thymeleaf模板中可使用以下方式,在发送HTTP请求的时候携带CSRF Token。若是是先后端分离的应用,或者其余模板引擎,酌情从cookies中获取CSRF Toekn。跨域

5.1.在Header中携带CSRF token

var headers = {};
headers['X-CSRF-TOKEN'] = "${_csrf.token}";
$.ajax({    
    headers: headers,    
});复制代码

5.2.直接做为参数提交。

$.ajax({    
    data: {      
       "_csrf": "${_csrf.token}"        
    }
});复制代码

5.3.form表单的隐藏字段

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">复制代码

期待您的关注

相关文章
相关标签/搜索