Spring Security 中 CSRF
从刚开始学习 Spring Security 时,在配置类中一直存在这样一行代码:http.csrf().disable();如果没有这行代码导致用户无法被认证。这行代码的含义是:关闭 csrf 防护。
一、
CSRF是指跨站请求伪造(Cross-site request forgery)
是web常见的攻击之一,攻击方通过伪造用户请求访问受信任站点。
通常的CSRF攻击方式如下
你登录了网站A,攻击者向你的网站^账户发送留言、伪造嵌入页面,带有危险操作链接。
当你在登录状态下点击了攻击者的连接,因此该链接对你网站^的账户进行了操作。
我这边是spring boot项目,在启用了@EnableWebSecurity注解后,csrf保护就自动生效了。
所以在默认配置下,即便已经登录了,页面中发起PATCH,POST,PUT和DELETE请求依然会被拒绝,并返回403,需要在请求接口的时候加入csrfToken才行。
如果你使用了freemarker之类的模板引擎或者jsp,针对表单提交,可以在表单中增加如下隐藏域:
<input type = “hidden” name = “${_csrf.parameterName}” value = “${_csrf.token}” />
如果您使用的是JSON,则无法在HTTP参数中提交CSRF令牌。相反,您可以在HTTP头中提交令牌。一个典型的模式是将CSRF令牌包含在元标记中。下面显示了一个JSP示例:
<html>
<head>
<meta name = “_csrf” content = “${_csrf.token}” />
<!-- 默认标题名称是X-CSRF-TOKEN -->
<meta name = “_csrf_header” content = “${_csrf.headerName}” />
</ head>
然后,您可以将令牌包含在所有Ajax请求中。如果您使用jQuery,可以使用以下方法完成此操作:
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$.ajax({
url:url,
type:'POST',
async:false,
dataType:'json', //返回的数据格式:json/xml/html/script/jsonp/text
beforeSend: function(xhr) {
xhr.setRequestHeader(header, token); //发送请求前将csrfToken设置到请求头中
},
success:function(data,textStatus,jqXHR){
}
});
在pom中添加相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- Security (used for CSRF protection only) -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
</dependencies>
二、禁用csrf防护机制
在SpringSecurity主配置文件中添加禁用crsf防护的配置。
在认证页面携带token请求
注:HttpSessionCsrfTokenRepository对象负责生成token并放入session域中。