samesite设置让跨域jsonp中cookie无法传递问题

最近项目中遇到一个问题,就是a.com域名下使用b.com域名的jsonp获取数据,竟然无法把b.com的cookie上发。

一)发现问题
 1)确认浏览器版本,chrome的83.0.4103.116版本,无法上发跨域cookie
 2)测试其他浏览器版本,QQ浏览器10.6(Chromium70.0.3538.25),可以正常上发跨域cookie
 3)查找差异性,因为是cookie问题,我们服务端写cookie是使用php的setcookie方法,所以我们查找php.net官网setcookie方法,我们发现了一个设置值,就是cookie的samesite这个属性。见后面参考1。

 

二)什么是samesite
 samesite最早出自草案:https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02
 Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击和用户追踪。以前samesite默认为None。
 chrome升级到80后,把samesite默认值设为lax,导致了jsonp传递cookie的问题。
 我们可以通过chrome的地址访问:chrome://flags/
 查找samesiite,就可以找到实验室中的几个选项,只要禁用第一个选项,就可以上发cookie了。但是有没有其他不禁用的方法,因为这个版本默认就开启了,不可能让用户来手动设置,所以我们需要了解一下这是个什么东西。

 

 Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。
 它可以设置三个值:Strict,Lax和None。

 1)Strict值,严格,完全禁止第三方cookie,跨站时,任何情况都不发送cookie。

Set-Cookie: CookieName=CookieValue; SameSite=Strict;

 2) Lax,稍微宽松,大多数情况也不发送第三方cookie,但是导航到目标地址的Get请求除外。

Set-Cookie: CookieName=CookieValue; SameSite=Lax;

 导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。

请求类型 示例 正常情况 Lax
链接 <a href="..."></a> 发送 Cookie 发送 Cookie
预加载 <link rel="prerender" href="..."/>  发送 Cookie 发送 Cookie
GET 表单 <form method="GET" action="..."> 发送 Cookie 发送 Cookie
POST 表单 <form method="POST" action="..."> 发送 Cookie 不发送
iframe <iframe src="..."></iframe> 发送 Cookie 不发送
AJAX $.get("...") 发送 Cookie 不发送
Image <img src="..."> 发送 Cookie 不发送

 

 设置了Strict或Lax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。

 3)None,chrome默认lax,但是我们网站可以显式关闭SameSite属性,设置为None既可。但是前提必须设置Secure属性为true,否则设置无效。

//无效
Set-Cookie: widget_session=abc123; SameSite=None
//有效
Set-Cookie: widget_session=abc123; SameSite=None; Secure

三)php中设置带SameSite的cookie
 1)服务器通用配置
 1.1)apache通用配置

Header always edit Set-Cookie (.*) "$1; SameSite=Lax"

 1.2) nginx通用配置

location / {
    # your usual config ...
    # hack, set all cookies to secure, httponly and samesite (strict or lax)
    proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
}

 2)PHP >= v7.3,可以直接设置samesite

setcookie($name, $value, [
    'expires' => time() + 86400,
    'path' => '/',
    'domain' => 'domain.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'None',
]);

 3)PHP <v7.3,无法直接设置samesite

//通过header设置
header("Set-Cookie: key=value; path=/; domain=example.org; HttpOnly; SameSite=Lax");
//通过setcookie方法设置,利用path传入"/;samesite=None",这是利用php的一个bug,不会对path里面的“;”进行处理
setcookie('cookie-name', '1', 0, '/; samesite=strict');

四)参考

 1)php设置cookie方法:

  https://www.php.net/manual/en/function.setcookie.php

 2)php中setcookie的bug可以查看:

  https://github.com/php/php-src/commit/5cb825df7251aeb28b297f071c35b227a3949f01

 3)Cookies:HTTP状态管理机制草案05:

  https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05

 4)samesite兼容内容:

  https://www.chromium.org/updates/same-site/incompatible-clients

 

posted @ 2020-08-27 16:09  hlsblog  阅读(3733)  评论(0编辑  收藏  举报