开发者学堂课程【Spring Security知识精讲与实战演示(一):Spring Security的 csrf 防护措施】学习笔记与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/730/detail/13035
Spring Security的csrf防护措施
已经使用了自定义认证页面而且认证也通过了。但是目前的后台系统很容被 csrf 攻击,此时就需要防止被攻击。
csrf攻击:目前网站正在开着,并且已经登录。但同时又开着另一个网站。两个网站登录着同一个浏览器,如果另一个网站有 csrf 攻击的病毒,病毒就可以获取整个浏览器中的Cooke信息(包含 Spring Security 网站中的认证信息),得到信息之后就可以伪造登录网站。
这时这个网站就不安全了。所以必须要使csrf这个过滤器起到作用还能保证后天管理系统是安全的。
怎样使用csrf?
看过滤器内的源码是什么样的。现在将CsrfFilter拿过来,来到Spring Security.xml,按两次shift。
点击进去,找主要的方法就是do filter Internet。在这个方法中可以看到上面是在验证token。如果没有token,就会直接看出页面不存在。Token从哪里拿?网站中有一个专门的生成token的工具类。
通过httpSessionCsrfTokenRepositorf将token放在session中。这个token的生成无需关注。
If else如下图,分了两个分支。
首先看If,先做了一个判断,如果满足这个条件,就会直接放行不再做任何的处理。里面经过了requestcsrfprotionmatcher,点击进去。
有上图的属性。给它赋值:DEFAULT-CSRF-MATCHER。继续点击。
可以看到后面的new csrffilter,还是当前的实例方法。因为使用实例调出来的。继续点击进去。
Arrays aslist指的是返回一个list。如果是GET、HEAD、TRACE、OPTIONS请求,csrf就不做处理直接放行。除了上面列举出来之外的请求,都是要判断的。例如POST请求、DELETE请求、PUT请求都会被拦截。GET、HEAD、TRACE、OPTIONS请求都不会给数据库造成影响。GET只是查询。但是增加POST、删除DELETE、改正PUT这些请求会对数据库内的数据进行改变。凡是对数据进行改变的视为安全性比较高的,是不能随意操作的。因此需要对POST、DELETE、PUT这些请求进行csrf拦截。
因为当前的method方式是POST,所以这个地方在不关闭的情况下必须默认经过csrf过滤器。需要走到else,但是请求的时候需要将携带刚刚的token。
在login中只提供了用户名和密码信息,还需要添加一个信息。
在please sign in中F12隐藏了一个信息。
需要将上图标蓝的信息给过滤器,因为每次token的信息都是不一样的。每次的token是动态生成的,是不一样的。不把信息给过滤器,csrffilter是获取不到的。获取不到就会出现Invalid CSRF found for异常。
目前首先需要csrf拦截,不能继续将过滤器security:csrf disable=“true”关闭。需要默认过滤器security:csrf disable=“true”是开启的状态。
但是开启之后再认证又报错了,这时候想要成功需要在login中携带token信息。但是不能直接粘贴上图标蓝的信息。因为不知道后面的值是什么,难道需要每次动态获取吗?实则无需这么麻烦。
在login中引入Spring Security动态标签:<%@taglib url prefix=”security”%>。动态标签中的security这个名字可以随便写。
上图标签想要使用需要导出taglib的包。不导出是无法使用的。上图标签必须写在对应的位置,写在外面就没用了。
例如写在了外面:有一个csrfInput,下面还有一个csrfMetaTage.这两个都是但是用的地方不一样。前面的是专门和from表单用的。如果from表单需要携带token,就是用上面的。如果不是from表单,是阿贾克斯请求就用下面的个csrfMetaTage.ing framework在paid里面写。所以在这里就使用csrfInput即可。写了csrfInput这个标签之后就相当于上图标蓝的内容,而且后面是动态的。里面变成什么,拿到的就会相应的改变。
目前csrf就已经设置完成了。现在验证一下。
为了防止项目有缓存,可以将target目录删掉。接下来直接启动。
这时需要注意,如果再次认证通过,就意味着现在的安全通过是绝对安全的。
但是也需要说明一个情况,既然源码中已经写道了,那么之后在写请求方式的时候需要注意,不可以随意乱写。例如需要修改数据,必须使用post。添加就需要使用post。如果还使用之前的随机页面写,不写method=post,就会默认get,但是get的安全性是没有保障的。因为get是不会经过csrf过滤器的。因此需要注意对应的操作使用对应的请求方式,一定要规范。
使用user用户名登录,点击登录,通过了。
这次的通过认证就真正被csrf过滤器保护了。