两种方案:
- 将 token 放在 cookie 里;
- 将 token 放在请求头里,用 Authorization 字段。
无论对于前端还是后端而言,这两种方案都是各有利弊的,下面稍微讲几点,实际开发中根据需求来选用即可。
将 token 放在 cookie 里:
前端可以完全不写代码,设置 cookie 可以依赖后端的 Set-Cookie
响应头,同域名的情况下发送所有请求的时候 cookie 也是自动带上的(也有坏处,这样经常会造成网络流量和带宽的浪费,所以 CDN 的域名都是和主站不同的,避免请求带上 cookie 浪费流量);
在安全性方面,cookie 可以设置 HttpOnly
来保护 cookie 无法被 JS 代码捕获,避免 XSS 等攻击,还可以设置 Secure
来确保只在 https 环境下传输 token;这些能力由浏览器提供,Authorization 无法实现;
但是,cookie 会存在 CSRF 攻击的问题,虽然浏览器厂商在逐步禁止第三方 cookie(似乎推迟到 2024 年了),但是这个问题还是不得不防(如果想使用第三方 cookie,可以在后端响应中设置 cookie 的 SameSite 属性);
在一级域名相同的情况下,cookie 可以实现跨子域名互通,比如 a.example.com 和 b.example.com 之间可以实现 cookie 互通(设置 cookie 时提供 Domain=example.com 属性),这个能力也是 Authorization 不具备的;
网页中的图片 <img />
请求时也会自动带上 cookie,好处是便于控制网络图片的访问权限,例如网络相册的权限控制可以精确到用户级,这个是 Authorization 做不到的,它必须把 token 放在 url 查询里面才行;缺点:如果网页中的背景图、icon 等资源图片放在相同的域名下,每次请求这些资源图片都会带上 cookie,很浪费带宽和服务器的流量, 所以 CDN 的域名一定要和主域名区分开。
将 token 放在请求头里,用 Authorization 字段:
此字段需要由 JS 代码来写入,请求想要带上 Authorization
字段则需要用 JS 代码来给请求方法添加全局拦截器,因此它天生具备防止 CSRF 的功能;
只有浏览器使用 cookie,而 Node.js 等环境是没有 cookie 的(评论区有人补充,现在小程序也可以支持 cookie),只能使用 Authorization
;因为此字段完全由 JS 来操作;虽然它原生没有提供 cookie 的 Secure
、Expires
等功能,但你可以通过 JS 代码自行实现;
前端将 token 持久存储,一般会存储在 LocalStorage 里面,此时存在 XSS 攻击盗取 token 的问题(将 LocalStorage 里的 token 加密可以一定程度上避免此问题),而且它是无法跨域互通的,即使两个网站的一级域名相同也无法互通;
部分认证规范要求使用 Authorization
字段,例如 JWT,如果使用了相关的认证(尤其是第三方服务),则必须使用此字段。
Http Header 更通用啊,可以兼容一些不支持 cookie 的容器,比如小程序;
因为跨域cookies是不安全的,所以大部分浏览器都已经限制了跨域cookies
参考:https://www.zhihu.com/question/558219586/answer/2710675882
https://zhuanlan.zhihu.com/p/395273289