Cook Cookie, 我把 SameSite 给你炖烂了

什么样的知识,最好吃?入口即化的php

github地址html

啰里吧嗦的开头

SameSite cookie 推出已一年有余,本身看了很多文章,也撞了很多南墙,因此仍是那句好记性不如烂笔头。你可能以为本身懂了,但试着讲出来,才能知道本身是否真的懂了。前端

列一列本身看过的文章:webpack

走进SameSite

和新冠一块儿火了的SameSite

SameSite Cookie行为更新去年就开始被提上日程,2020年2月随着Chrome 80的推出,这个属性开始正式生效,但由于3月份正是全球新冠肆虐的时候,当时的维护者都还活在新冠的恐惧之下,网站无法及时更新,这项政策致使不少网站瘫痪,chrome官方又在4月进行了回滚,暂时终止了这项策略。直到2020年7月14日Chrome 84稳定版开始,从新恢复SameSite cookie策略,而且会逐步部署到Chrome 80以及以上的版本中。git

若是你知道CSRF,那你就知道这项攻击真正的核心就是利用 cookie 自动携带的行为(进一步讲就是跨站携带cookie)。github

之因此会跨站携带,是由于起初 cookie 的规范中并无 SameSite 这个属性;直到2016年first-party-cookies草案的推出,但并有多少人真正去用,而浏览器这边的实现也默认是SameSite=None,因此对开发者并无什么影响,天然就没有引发多大的关注,至少不如此次,而提案初衷:改善安全和隐私泄露的问题。效果天然就不是很理想。web

为了解决这些问题,一个新的草案:Incrementally Better Cookies,在草案的开头,就直接说道:ajax

This document proposes two changes to cookies inspired by the properties of the HTTP State Tokens mechanism proposed in [I-D.west-http-state-tokens]. First, cookies should be treated as "SameSite=Lax" by default. Second, cookies that explicitly assert "SameSite=None" in order to enable cross-site delivery should also be marked as "Secure"

翻译成中文就是两个改进 算法

  1. "SameSite=Lax" 变成默认设置,取代如今的"SameSite=None";
  2. 若是硬要设置成"SameSite=None",则须要同时增长"Secure"标识,即这个cookie只能在Https连接上传输;

first-party-cookies 草案规定了什么

草案那么长,我就关(kan)注(dong)了一段话:
20201208223403chrome

能够简单理解为同站 和 跨站的定义,中文大白话翻译就是:

  1. 若是请求的url是空,则浏览器须要以domain为请求的地址;好比 closertb.site 网站html有这样一个<script src="/static/index.js"></script> 标签,那最后浏览器发出的请求就是:closertb.site/static/index.js,这没得说,确定是同站;
  2. 若是请求domain 和 浏览器地址栏url匹配(注意是匹配,不是相等),也是同站;
  3. 除此之外,都是跨站;

好家伙,感受说了和没说同样;而后定义了SameSite语义:

“ SameSite”限制了cookie的使用范围,以便它 仅在这些请求是“相同站点”时附加到请求中, 由2.1节中的算法定义。例如,要求 对于“ https://example.com/sekrit-image”, 将附加相同站点的cookie 即当且仅当从其站点为“example.com”。

但在接下来的几节,并无出现StrictLaxNone 这些语义,我猜主要仍是这只是一份草稿,还不涉及到具体实现。

在最新的RFC6265 替代草案draft-ietf-httpbis-rfc6265bis-05, 说起了这三个属性值,并作了介绍,但貌似仍是落后如今浏览器的实现,由于草案中SameSite=None仍然是默认属性;

SameSite 的属性值及其区别

我以为这部分再讲就是蛋炒饭了,毕竟今年太多人讲过了,没啥意义。

你能够看:阮一峰老师

但更推荐MDN官方的:SameSite cookies

你能够经过:https://samesite-sandbox.glit... 网站来了解你的浏览器是否开启Incrementally Better Cookies(IBC)

20201214224921

用实例说话,到底限制的是什么?

直到如今,其实不少前端开发者对这个变化是无感的,主要两个缘由:

  • 鉴权token化,cookie更多充当存储;
  • 业务太简单,cookie使用的场景都是同站的,因此新规并无多大影响,新规是针对跨站作cookie携带限制的;

同站的影响是不大的

大多数公司cookie都是用来作单点登陆身份鉴权的,这种多数存在同站;好比:

  • 鉴权服务:sso.closertb.site
  • erp服务:erp.closertb.site
  • crm服务:crm.closertb.site
  • 其余服务:xxx.closertb.site

当用户初次打开crm服务网站时,会首先调用鉴权服务查询该用户是否已受权或受权有效?若是无效,就会重定向到sso.closertb.site网站让用户登陆受权,受权完成后,服务会在closertb.site种下几个cookie,用于识别用户身份,而后就重定向回crm.closertb.site网站;当用户再次打开crm服务或其余同站网站时,也会先调用鉴权服务,因为cookie还有效,因此用户就不用再去登陆了,能够继续在网站浏览。

20201227233737

以上就是一个很是典型的单点登陆设计,都是利用浏览器在同站请求会自动携带cookie来作身份识别的方式;

跨站才是重点

但还有一种稍微复杂的状况,跨站单点登陆,举个典型的例子:天猫和淘宝

20201228003050

这个状况复杂就复杂在淘宝和天猫是跨站的,当淘宝登陆了时,你再去访问天猫,会有一系列的鉴权操做:

20201228003949

但今天不是主讲淘宝天猫的单点登陆设计,主要是讲cookie,这里有一个设计,就是跨站cookie的使用;在用户登陆了淘宝后,用户再去打开天猫,由于天猫淘宝是一套用户体系,因此他们作了免登,就是截图所示,先是调用了了top-tmm.taobao.com/login_api.do, 这个请求会携带*.taobao.com域下的cookie, 从而服务端就能知道这个用户登陆过。因为请求是在 tmall.com 站点下发出的,因此这是一个跨站请求,这也是此次新规重点照顾的场景。

为了在新版本浏览器下,能继续让单点登陆有效,因此淘宝的开发也就作点改变来适应, cookie 都打上了samesite=None与secure标识, 利用改进第二条规则。

20201228215342

因为Secure的限制,要携带的跨站点请求必须在带有安全标识站点下发出请求

因此当你输入http://tmall.com,站点302必会重定向到https://tmall.com 安全域名下。

除了上面这种故意设计的跨站,还有不少其余形式,已经有高手总结过,我就发一个我我的以为比较全的,来自知乎

20201228230504

对开发的影响

虽然咱们大多数开发开发的站点都是同站,但在本地调试时,基本都是在http://localhost:port站点下进行,要拿到登录态,面临的状况都是跨站。因此为了应对此次更新,通常有两种方法来解决:修改安全限制修改调试站点域名

修改安全限制就像
关闭跨域限制同样,只须要打开chrome://flag站点进行设置,以下图所示:
20201228223230

上面那种改动粗暴,虽然有效,但不适合咱们文化人,文化人就得干点文化人该干的事,修改调试站点地址, 好比:

  • 本地server 站点地址 localhost:8906 切换到local.closertb.site,通常来讲都须要修改webpack host地址;
  • 给local.closertb.site加本地解析,说人话,就是修改host解析
  • 浏览器访问,看看效果

一些前端要懂的服务端知识

同源 VS 同站 或 跨域 VS 跨站

同源,基本上懂行的前端都知道,只有请求的地址与站点是同协议、同域名、通端口,才能称为同源,除此之外,都是跨域;

而同站就没这么严格,简单看看同站定义:只要两个 URL 的 eTLD + 1 相同便可,不须要考虑协议和端口。

其中,eTLD 表示有效顶级域名,注册于 Mozilla 维护的公共后缀列表(Public Suffix List)中,例如,.com、.co.uk、.github.io 等。eTLD+1 则表示,有效顶级域名+二级域名,例如taobao.com等。

举几个例子,www.taobao.com和www.baidu.com是跨站,www.a.taobao.com和www.b.taobao.com是同站,a.github.io和b.github.io是跨站(注意是跨站)。

为何a.github.io和b.github.io是跨站,由于 github.io 是有效顶级域名

再来些零碎的

1.虽然同站能够携带cookie,但跨了域的同站请求不会主动携带,fetch须要设置credentials属性为include(ajax有类似设置), 但这只是开始,由于设置了这个属性携带了cookie后,这个请求就变成了非简单请求,服务端须要针对请求的站点设置Access-control-Allow-Credentials,如图下;
20201203215510
20201216220316
20201203212417
2.服务端 set-cookie 也须要遵循同站规则,不然不生效;eg: 当前网站域名local.closertb.site, 登陆发送请求/user/login,但该请求向admin.closertb.site种了一个cookie, 这个玩法就是非法的(管太宽),这个请求仅可种domai为'local.closertb.site' 或 'closertb.site';为无效时,浏览器会标黄提醒
20201216222016

3.cookie 的path 是针对于请求地址的,和当时浏览器地址无关;path 经常使用于多个服务经过一个网关来给前端提供接口,为尽可能区分各个服务的cookie,因此有这个path属性设置,这样能够减小请求携带的cookie数量;图下所示的cookie,就只会在请求地址是以/rule 开头时才携带,其余地址就会忽略;
20201203212610
20201203212417

4.ajax 和 fetch 请求,响应302, 是不能直接改变浏览器地址进行跳转的,除非前端手动去操做;这就是为何咱们会说ajax 和 fetch 是先后端分离的开始,由于之前不少jsp 或 php页面,若是用户没有权限,就302重定向到登陆页;而先后端分离后,更常见的作法是响应401,而后前端再手动跳转到登陆页;

公众号:前端黑洞

打个广告

阿里本地生活成都、杭州、上海三地招前端、测试、后端,有意的能够发简历到我邮箱,也能够加我微信咨询。 微信号:5娃4娃5幺娃34.。。

相关文章
相关标签/搜索