SameSite - 解决篇

1,765 阅读3分钟

了解了原理,要处理相关问题其实就很简单了

1. cookie如何进行设置?

其实解决方案很简单,我们可以自己写一个方法来对cookie进行赋值,给所有(需要)的跨站的cookie的值都追加不设置任何属性的值和设置None的值

function setCookie(cookieString, canCrossSite) {
    document.cookie = `${cookieString}`;
    if(canCrossSite) {
        document.cookie = `${cookieString}; SameSite=None; Secure`;
    }
}

2. 什么时候进行设置?

方案有了,那么应该在什么时候执行方法呢?

根据自己的了解,浏览器设置cookie一般通过两个途径:通过Javascript API和请求头的Set-Cookie

2.1、通过Javascript API

通过Javascript API有两种方式,第一种是我们最常用的document.cookie=xxx的方式,将cookie中放入需要的数据;另一种是通过Browser Extensions,可以获取到Cookie对象进行操作。

所以针对通过Javascript API设置的方式,我们只需要将以前通过document.cookie=xxx的方式,修改为我们自定义的setCookie方法来处理就可以了

2.2 通过请求Set-Cookie设置

通过请求头中携带Set-Cookie的头信息,可以完成后端请求给浏览器设置cookie,设置以后对于需要跨站请求的cookie就符合我们的预期,例如:

const http = require('http');
http.createServer((req, res) => {
    res.setHeader('Set-Cookie', ['key5=page2; SameSite=None; Secure', 'key6=page2']);
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.end('end');
}).listen(3001);

访问http://localhost:3001/index以后可以发现,请求cookie携带key6=page2

const http = require('http');
const fs = require('fs');
const server = http.createServer;
const options = {
    key: fs.readFileSync('./key.pem'),
    cert: fs.readFileSync('./cert.pem')
};
server(options, (req, res) => {
    console.log(req.url)
    if(req.url.indexOf('/index') > -1) {
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.end('index');
    } else {
        res.setHeader('Set-Cookie', ['key5=abc; SameSite=None; Secure;', 'key6=def;']);
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.end('end');
    }
}).listen(3001);

访问https://localhost:3001/index以后可以发现,请求cookie携带key5=page2key6=page2

前端也可以通过以上的方案按照自己的要求在异步请求结束的时候进行处理

function setCookieForSameSite() {
    let cookies = document.cookie.split(';');
    cookies.forEach(cookie => {
      // 但是值可能存在多个等号,但是第一个等号是区分key和value的界限
      // let [key, ...value] = cookie.trim().split('=');
      setCookie(cookie, true);
    });
}

PS:但是对于前端设置的情况需要注意,Set-Cookie设置的cookie仅仅针对请求的域名访问的时候增加携带cookie,如果当前域名和请求的域名不一致,可以发现document.cookie是无法获取到Domain非当前域名的cookie的(这一自己测试过一些例子,但是也没有特别清楚,如果有了解的可以一起探讨)

3. 其他

本来自己最开始的打算是给document.cookie赋值的时候增加监听,希望在统一层面给所有的cookie设置的时候都增加跨站属性,但是这样做存在两个问题:

第一,并非是所有的cookie都需要进行跨站处理的,通常,我们需要跨站处理的信息通常都是一些登陆信息,而对于其他的cookie信息设置跨站并没有很好的用处

第二,自己没有找到document.cookie设置时候的钩子,虽然一开始觉得是否可以考虑使用Object.defineProperty的方式

希望有更好解决方案的小伙伴能一起来讨论。