CSRF 攻击是什么
用户登陆了银行网站your-bank.com,银行服务器发来了一个 Cookie。
用户后来又访问了恶意网站malicious.com,上面有一个表单。
<form action="your-bank.com/transfer" method="POST">
...
</form>
用户一旦被诱骗发送这个表单,银行网站就会收到带有正确 Cookie 的请求。为了防止这种攻击,表单一般都带有一个随机 token,告诉服务器这是真实请求。
<form action="your-bank.com/transfer" method="POST">
<input type="hidden" name="token" value="dad3weg34">
...
</form>
这种第三方网站引导发出的 Cookie,就称为第三方 Cookie。它除了用于 CSRF 攻击,还可以用于用户追踪。
比如,Facebook 在第三方网站插入一张看不见的图片。
<img src="facebook.com" style="visibility:hidden;">
浏览器加载上面代码时,就会向 Facebook 发出带有 Cookie 的请求,从而 Facebook 就会知道你是谁,访问了什么网站。
SameSite是什么
Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。
可以设置三个值。
- Strict: 最为严格,完全禁止第三方 Cookie。
- Lax: 大多数情况也是不发送第三方 Cookie,Get 请求除外。
- None: 网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。
问题描述
- 以前设置Access-Control-Allow-Credentials: true和xhr.withCredentials = true,可以实现跨域传递Cookie,达到维持用户登录态等目的,但是会有CSRF的风险。所以,从Chrome 51开始,浏览器的Cookie新增加了一个SameSite属性,用来防止CSRF攻击和用户追踪, 默认是关闭的。
- 从
Chrome 80开始,浏览器的Cookie的SameSite属性会默认开启,用来防止CSRF攻击和用户追踪
Chrome 80的用户会出现set cookie失败的情况
前端暂时解决方案
后端解决方案
代码示例
private static void setSameSite(HttpServletResponse response){
Collection<String> headers = response.getHeaders(HttpHeaders.SET_COOKIE);
boolean firstHeader = true;
// there can be multiple Set-Cookie attributes
for (String header : headers) {
if (firstHeader) {
response.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None"));
firstHeader = false;
continue;
}
response.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None"));
}
}
Cookie cookie = new Cookie("CSESSIONID", csessionid);
cookie.setMaxAge(-1);
cookie.setPath("/");
//解决chrome 78版以上跨域问题
cookie.setSecure(true);
// 并写回浏览器
response.addCookie(cookie);
setSameSite(response);
使用Nginx的proxy_cookie_path功能
如果站点Cookie所在目录在根目录/下,设置如下:
proxy_cookie_path / “/; secure; SameSite=None”;
如果站点Cookie所在目录在abc目录下,设置如下:
proxy_cookie_path /abc/ “/abc/; secure; SameSite=None”;
如果无法确定站点Cookie目录,可使用Chrome开发者工具,监测Network下网络请求,找到 Response Headers中set-cookie属性值,该值中有path属性值即为Cookie目录,也即上文要替换的/或者/abc/值。
因为设置sameSite为None之后,CSRF的风险又回来了。所以,换成token的检验方式而不依赖Cookie,才是最好的解决方式。

相关文档
CSRF 攻击是什么
用户登陆了银行网站your-bank.com,银行服务器发来了一个 Cookie。
用户后来又访问了恶意网站malicious.com,上面有一个表单。
用户一旦被诱骗发送这个表单,银行网站就会收到带有正确 Cookie 的请求。为了防止这种攻击,表单一般都带有一个随机 token,告诉服务器这是真实请求。
这种第三方网站引导发出的 Cookie,就称为第三方 Cookie。它除了用于 CSRF 攻击,还可以用于用户追踪。
比如,Facebook 在第三方网站插入一张看不见的图片。
浏览器加载上面代码时,就会向 Facebook 发出带有 Cookie 的请求,从而 Facebook 就会知道你是谁,访问了什么网站。
SameSite是什么
Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。
可以设置三个值。
问题描述
Chrome 80开始,浏览器的Cookie的SameSite属性会默认开启,用来防止CSRF攻击和用户追踪Chrome 80的用户会出现set cookie失败的情况前端暂时解决方案
打开
Chrome设置,chrome://flags禁用
SameSite副作用:会出现warning提示
后端解决方案
后端服务域名必需使用https协议访问
SameSite属性的值改为None
secure属性设置为true
后端要判断浏览器的
user-agent属性,Chrome58前,没有SameSite属性,要注意!代码示例
使用Nginx的proxy_cookie_path功能
如果站点Cookie所在目录在根目录/下,设置如下:
如果站点Cookie所在目录在abc目录下,设置如下:
如果无法确定站点Cookie目录,可使用Chrome开发者工具,监测Network下网络请求,找到 Response Headers中set-cookie属性值,该值中有path属性值即为Cookie目录,也即上文要替换的/或者/abc/值。
相关文档