如何理解 cookie
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据。
主要特点:
由服务器生成,浏览器进行存储
浏览器 每次请求时会自动携带对应域名下的 cookie
可设置过期时间
默认情况下随着浏览器关闭而删除(会话 cookie)
1. SameSite=Strict
-
描述:这是最严格的模式。当
SameSite属性设置为Strict时,浏览器只会在同站请求时发送该 Cookie,也就是说只有当请求的源(协议、域名和端口)与设置 Cookie 的源完全一致时,才会带上这个 Cookie。 -
示例场景:当用户在银行网站登录后,银行网站设置了
SameSite=Strict的 Cookie。如果用户从另一个网站点击链接访问银行网站,这个 Cookie 不会被发送,从而避免了潜在的 CSRF 攻击。 -
SameSite=None -
描述:这个值表示浏览器在同站和跨站请求时都会发送该 Cookie,但必须同时设置
Secure属性,即该 Cookie 只能通过 HTTPS 协议传输,以确保数据在传输过程中的安全性。
SameSite=Lax
- 描述:这是一种相对宽松的模式。在这种模式下,浏览器在同站请求时会发送 Cookie,并且在一些跨站的顶级导航(如通过链接、GET 表单等发起的跨站请求)中也会发送 Cookie,但对于跨站的 POST 请求、AJAX 请求和
<iframe>等不会发送 Cookie。
常用属性:
- name:cookie 名称
- value:cookie 值
- domain:指定 cookie 所属域名
- path:指定 cookie 所属路径
- expires/max-age:过期时间
- secure:只在 HTTPS 下传输
- httpOnly:禁止 JS 访问
- sameSite:跨站点请求限制
使用场景:
- 会话状态管理(用户登录状态、购物车等)
- 个性化设置(用户偏好、主题等)
- 浏览器行为跟踪(分析用户行为等)
限制:
- 大小限制:通常为 4KB
- 数量限制:每个域名下的 cookie 数量有限
- 安全性:明文传输(除非使用 HTTPS)
- 作用域:只能在所属域名下使用
如何理解 Session
Session 是服务器端的会话管理机制:
基本概念
- 服务器为每个用户创建的临时会话存储空间
- 用于保存用户的会话状态
- 通过 SessionID 来识别不同用户
- SessionID 通常保存在 Cookie 中
工作流程
- 用户首次访问服务器时,服务器创建 Session 并生成 SessionID
- 服务器将 SessionID 通过 Cookie 发送给客户端
- 客户端后续请求会自动携带包含 SessionID 的 Cookie
- 服务器通过 SessionID 找到对应 Session 并识别用户
特点
- 安全性较高:敏感数据存储在服务器
- 服务器负载较大:需要存储所有用户的 Session
- 依赖 Cookie:通常需要 Cookie 来存储 SessionID
- 集群问题:需要考虑 Session 共享
使用场景
- 用户登录状态管理
- 购物车
- 权限验证
- 表单验证
与 Cookie 的区别
- 存储位置:Session 在服务器,Cookie 在客户端
- 安全性:Session 较安全,Cookie 相对不安全
- 存储容量:Session 容量较大,Cookie 通常限制 4KB
- 性能:Session 消耗服务器资源,Cookie 消耗带宽资源
什么是 JWT
JWT (JSON Web Token) 是一种开放标准,用于在各方之间安全地传输信息。
组成部分(用 . 分隔的三部分):
- Header(头部):指定加密算法和令牌类型
- Payload(负载):包含声明(claims)的实际数据
- Signature(签名):对前两部分的签名,用于验证消息未被篡改
工作流程:
-
用户登录成功后,服务器创建 JWT
- 设置 Header 和 Payload
- 使用密钥生成签名
- 将三部分组合成 token
- 服务器将登录凭证做数字签名,加密之后得到的字符串作为token
-
服务器将 token 返回给客户端
- 客户端存储在 localStorage 或 cookie 中
-
后续请求携带 token
- 通常放在 Authorization header
- 格式:
Bearer <token>
-
服务器验证 token
- 检查签名是否有效
- 验证是否过期
- 验证其他声明(claims)
特点:
- 无状态:服务器不需要存储会话信息
- 可扩展:负载部分可以包含自定义数据
- 跨域友好:可以在不同域名下使用
- 性能好:验证在服务端完成,不需要查询数据库
安全考虑:
- 不要在 payload 中存储敏感信息
- 设置合理的过期时间
- 使用 HTTPS 传输
- 妥善保管签名密钥
JWT
在目前前后端分离的开发过程中,使用token鉴权机制用于身份验证是最常见的方案,流程如下:
- 服务器当验证用户账号和密码正确的时候,给用户颁发一个令牌,这个令牌作为后续用户访问一些接口的凭证
- 后续访问会根据这个令牌判断用户时候有权限进行访问
Token,分成了三部分,头部(Header)、载荷(Payload)、签名(Signature),并以.进行拼接。其中头部和载荷都是以JSON格式存放数据,只是进行了编码。
header
每个JWT都会带有头部信息,这里主要声明使用的算法。声明算法的字段名为alg,同时还有一个typ的字段,默认JWT即可。以下示例中算法为HS256
{ "alg": "HS256", "typ": "JWT" }
因为JWT是字符串,所以我们还需要对以上内容进行Base64编码,编码后字符串如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
payload
载荷即消息体,这里会存放实际的内容,也就是Token的数据声明,例如用户的id和name,默认情况下也会携带令牌的签发时间iat,通过还可以设置过期时间,如下:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
同样进行Base64编码后,字符串如下:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
Signature
签名是对头部和载荷内容进行签名,一般情况,设置一个secretKey,对前两个的结果进行HMACSHA25算法,公式如下:
Signature = HMACSHA256(base64Url(header)+.+base64Url(payload),secretKey)
一旦前面两部分数据被篡改,只要服务器加密用的密钥没有泄露,得到的签名肯定和之前的签名不一致。
生成 token
借助第三方库jsonwebtoken,通过jsonwebtoken 的 sign 方法生成一个 token:
- 第一个参数指的是 Payload
- 第二个是秘钥,服务端特有
- 第三个参数是 option,可以定义 token 过期时间
在前端接收到token后,一般情况会通过localStorage进行缓存,然后将token放到HTTP请求头Authorization 中,关于Authorization 的设置,前面要加上 Bearer ,注意后面带有空格。
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token');
config.headers.common['Authorization'] = 'Bearer ' + token; // 留意这里的 Authorization
return config;
})
优缺点
优点:
- json具有通用性,所以可以跨语言
- 组成简单,字节占用小,便于传输
- 服务端无需保存会话信息,很容易进行水平扩展
- 一处生成,多处使用,可以在分布式系统中,解决单点登录问题
- 可防护CSRF攻击
缺点:
- payload部分仅仅是进行简单编码,所以只能用于存储逻辑必需的非敏感信息
- 需要保护好加密密钥,一旦泄露后果不堪设想
- 为避免token被劫持,最好使用https协议
token存储在哪里
1. Cookie
-
优点
- 可以设置
HttpOnly属性,防止通过 JavaScript 脚本访问,降低了 XSS 攻击时 token 被窃取的风险。 - 可以设置
SameSite属性,控制跨站请求时 cookie 的发送,增强安全性。 - 浏览器会自动在请求中携带 cookie,无需手动添加。
- 可以设置
-
缺点
- 有大小限制,通常为 4KB 左右。
- 容易受到 CSRF 攻击,不过可以通过设置
SameSite和Secure属性来缓解。
-
使用场景:适用于传统的 Web 应用,尤其是需要频繁与服务器进行交互,且对安全性有一定要求的场景。
2. LocalStorage
-
优点
- 存储容量较大,一般为 5MB 左右。
- 数据会一直存储在浏览器中,除非手动删除,适合长期保存 token。
-
缺点
- 没有
HttpOnly属性,容易受到 XSS 攻击,token 可能会被窃取。 - 存储在本地,数据不会自动随请求发送到服务器,需要手动添加到请求头中。
- 没有
-
使用场景:适用于单页面应用(SPA),需要在页面刷新或关闭后仍然保持用户登录状态的场景。
3. SessionStorage
-
优点
- 存储容量与
localStorage相当。 - 数据仅在当前会话期间有效,关闭浏览器窗口后数据会自动清除,安全性相对较高。
- 存储容量与
-
缺点
- 同样没有
HttpOnly属性,存在 XSS 攻击风险。 - 数据不会自动随请求发送到服务器,需要手动添加到请求头中。
- 同样没有
-
使用场景:适用于临时保存 token,如用户在一次会话中进行的操作需要身份验证的场景。
token可以存储在: cookie 和 localstorage 和 sessionstorage 区别:
最好是放在localstorage中,更加的灵活
前端数据存储
-
Cookie
- 简介:Cookie 是由服务器发送到用户浏览器并存储在本地的小文件,通常用于跟踪用户会话、存储用户登录信息、记录用户偏好等。
- 特点:它会在每次浏览器请求相关域名的页面时被发送到服务器,因此可以用于在不同页面之间传递数据。不过,Cookie 的大小有限制,一般不超过 4KB,且过多的 Cookie 会影响网站的性能。在http中明文传输不安全。
-
Local Storage
- 简介:Local Storage 是 HTML5 提供的一种在客户端本地存储数据的机制,它将数据存储在用户的浏览器中,并且没有时间限制,除非用户手动清除或通过代码删除,否则数据将一直存在。
- 特点:它提供了更大的存储空间,一般浏览器支持的容量在 5MB 到 10MB 左右,并且数据不会随着每次 HTTP 请求发送到服务器,适合存储不经常变化且需要长期保存的数据,如用户的配置信息、离线应用程序的数据等。(用户的浏览器偏好设置,隐私主题选择)
-
Session Storage
- 简介:Session Storage 与 Local Storage 类似,但它的生命周期与浏览器会话相关。当用户关闭浏览器窗口或标签页时,存储在 Session Storage 中的数据会被自动删除。
- 特点:它也提供了相对较大的存储空间,适用于存储仅在当前会话中需要使用的数据,例如用户在一个购物网站的单次购物过程中的临时数据。填写多步骤表单数据,
-
IndexedDB
- 简介:IndexedDB 是一种低级别的数据库 API,用于在浏览器中存储大量结构化数据。它允许创建数据库、定义对象存储、建立索引以及执行各种数据库操作,如插入、查询、更新和删除数据。
- 特点:IndexedDB 具有异步操作、支持事务、存储空间大等特点,适合存储大量的复杂数据,如图片、视频等多媒体数据,或者用于开发离线应用程序时存储大量的业务数据。
cookie 和 localstorage 和 sessionstorage
共同点:都保存在浏览器端,都不支持跨域;
不同点:
- 存储内容是否发送到服务器:
- 数据存储上大小的不同
- 数据存储的有效期不同
- 作用域不同:cookie和localstorage在同源同窗口中都是共享的 ,session storage不同的窗口不共享(即使是同一个页面)
使用场景:
在客户端和服务器之间共享数据+长期存储:cookie 只需要在客户端长期存储+不需要和服务器交互 :localstorage 只在客户端+会话期间暂存 :sessionstorage
SSO 单点登录
单点登录(Single Sign-On,SSO)是一种身份验证和授权机制,它允许用户使用一组凭据(如用户名和密码)登录到一个系统后,无需再次输入凭据,即可访问多个相互关联的系统或应用程序。
实现方式
- 基于令牌的方式:如 JSON Web Token(JWT),认证中心在用户登录成功后生成一个包含用户身份信息的 JWT 令牌,应用系统通过验证令牌的有效性来确认用户身份。
- 基于 Cookie 的方式:认证中心在用户登录成功后设置一个全局的 Cookie,当用户访问其他应用系统时,应用系统通过检查该 Cookie 来判断用户是否已经登录。
用户登录,认证中心会生成session会话,保存用户信息;将session id通过cookie返回给用户。用户保存cookie,然后下一次登录子系统的时候,将包含session id的cookie发送给子系统,子系统会根据session id 去认证中心去查询是否有用户信息。如果有,返回相应 的资源。 优点:绝对的控制权。缺点:很花钱,要维护数据库;而且一旦认证中心坏掉,就完蛋了。
单token:对用户的控制变弱。
双token 的模式。一个短token(时效短),一个刷新token(时效长)
短token 失效,就用刷新token 去认证中心,拿到新的token,再发送给子系统。
用户需要时不时的刷新token。