cookie SameSite属性

cookie之SameSite属性

问题描述:

前端调取后端返回base64编码格式字符串验证码的接口,response返回set-Cookie

Set-Cookie: laravel_session=eyJpdiI6IlNKbDdBeU5PdjBVOFJsYnpYSmRLRHc9PSIsInZh
bHVlIjoiekdRc2ZMQWpLNlJHTE9MM1RyRnhPUFVnN0RyNmRcLytnK1NFa1p3MElNMWNRODFTampG
ZjhGanVxenhOUldjc3oiLCJtYWMiOiI3NjE3MTg0MGU4NWM5ZDcyYzkzNjIwNDkxMGI0NGI4ZWE3
NmZjOWQ3OWQxMGNlOWRmYmI1ZGQwNzljZGVkMmMxIn0%3D; expires=Thu, 17-Sep-2020 
08:37:53 GMT; Max-Age=7200; path=/; httponly

但无法在前端域名下创建cookie保存sessionId,导致登录接口取不到session存储的验证码

原因:

搜索chrome未携带cookie原因,发现cookie新属性:SameSite(chrome77版本后支持) 。对该属性的介绍可以参考这篇文章:SameSite。同时,查看chrome的cookie,由于没有指明SameSite的取值,chrome默认将其设置为了Lax:

解决方案:

1、设置response的header(推荐、必要条件HTTPS)

通过在后端中设置

("Set-Cookie", "HttpOnly;Secure;SameSite=None")

响应头可以看到设置的Set-Cookie,但是chrome提示:

由于设置SameSite为NONE时,需要同时设置secure,不设置secure无效,而设置secure之后,必须使用https来传输cookie。相对来说较为安全。

2、究极方案(修改Chrome配置)

在chrome中打开链接: chrome://flags/#site-isolation-trial-opt-out,搜索samesite

禁用相关配置即可

3、nginx反向代理解决

重要代码:

# 只支持 proxy 模式下设置,SameSite 不需要可删除,如果想更安全可以把 SameSite 设置为 Strict
proxy_cookie_path / "/; httponly; secure; SameSite=Lax";

示例:

server {
    listen 443 ssl http2;
    server_name www.cat73.org;

    ssl_certificate /etc/letsencrypt/live/cat73.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cat73.org/privkey.pem;

    ssl_trusted_certificate /etc/letsencrypt/live/cat73.org/chain.pem;

    add_header X-XSS-Protection "1; mode=block";
    add_header X-Frame-Options SAMEORIGIN;
    add_header Strict-Transport-Security "max-age=15768000";

    location / {
        root /var/www/html;
    }

    location /api {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 在这里设置
        proxy_cookie_path / "/; httponly; secure; SameSite=Lax";
    }
}

4、前端代理解决方案

前端框架:React App
调试环境在package.json 文件加入代理配置项

"proxy": "代理地址"

之后运行调试环境 npm run start

框架相关代码

    // Load proxy config
    const proxySetting = require(paths.appPackageJson).proxy;
    const proxyConfig = prepareProxy(proxySetting, paths.appPublic);

总结:

存在即合理,SameSite的设计初衷是为了防止CSRF攻击,禁用SameSite实际上并没有解决问题,属于下下策。这里提供一下我的理解,SameSite为了防止CSRF攻击,加强了对cookie的管理,防止用户带着cookie去访问第三方网站,而这又涉及到了跨域问题。然而,我们不可能要求用户像我们一样去禁用新版chrome的SameSite,目前的建议就是在header中设置samesite,即上述的

("Set-Cookie", "HttpOnly;Secure;SameSite=None")

后,使用https传输cookie。

SameSite等级

1、Strict

Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。

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

这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。

2、Lax

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属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

下面的设置无效。

Set-Cookie: widget_session=abc123; SameSite=None

下面的设置有效

Set-Cookie: widget_session=abc123; SameSite=None; Secure

参考链接

1、链接1

2、链接2

3、链接3

4、链接4

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值