Cookie、Session 和 Token
Cookie:是浏览器里的一小块存储空间,由服务器通过Set-Cookie响应头种下,浏览器会在后续请求中带上。
关键属性:
- Name=Value :键值对
- Domain / Path: 作用域
- Expires / Max-Age :过期时间(不设就是会话级,关闭浏览器就消失)
- Secure:强制HTTPS
- HttpOnly:禁止JS读取
- SameSite:防CSRF
常见用途:
- 会话管理(存放Session ID)
- 个性化设置(语言、主题)
- 跟踪用户行为
局限:
- 大小4KB
- 每次请求自动发送,可能浪费带宽
- 跨域需复杂配置(CORS+withCredentials)
- 如果不设HttpOnly+Secure,容易被XSS窃取
Session:是“服务器存储+Cookie传ID”的组合方案。
工作流程:
- 用户登录,服务器创建Session,存入用户信息,生成Session ID。
- 响应头Set-Cookie把Session ID 给浏览器
- 后续请求浏览器自动带上Cookie,服务器根据Session ID找到存放在自己这里的Session,识别用户。4
特点:
- 有状态:状态存在服务器
- 安全性:客户端只看到无意义的ID,数据不会暴露
- 扩展性差:水平扩展需要共享Session
- 受CSRF威胁,因为浏览器自动带Cookie,还需要配合CSRF Token或SameSite
Token:是一种“无状态、自包含”的凭证,服务不需要存储会话。最典型实现:JWT(JSON Web Token)
JWT的结构:JWT由三部分自称,用 . 连接:Header.Payload.Signature
- Header:声明类型和签名算法,如:{"alg":"HS256","typ":"JWT"}
- Payload:存放“声明”(claims),如用户ID、角色、过期时间等。注意:Payload仅BASE64编码,不是加密,不能放密码等敏感信息!
- Signature:用Header指定的算法,对Header + "." + Payload进行签名,防止篡改。例如:HMACSHA256(base64(header) + "." + base64(payload), secret)
认证流程:
- 用户登录,服务器校验账号密码。
- 服务生成JWT,用密钥签名,返回给客户端。
- 客户端存储Token,在内次请求时通过Authorization:Bearer 头(或 Cookie)发给服务器。
- 服务器++只需要验证签名++,就可以从Payload中取出用户细腻系,无需查库或Session。
Token存在哪里?有什么安全问题?
存储位置1:localStorage / sessionStorage
优点:方便,不受自动发送限制
风险:容易被XSS,恶意脚本可以直接读取
存储位置2:HttpOnly Cookie
优点:JavaScript无法读取
风险:全自动发送,可能受CSRF威胁
存储位置3:内存
优点:最安全,关闭页面就丢失
风险:刷新页面需要重新获取,体验很差。
推荐做法:
- Access Token (短期)存在内存或者HttpOnly Cookie中,通过Authorization 头或者Cookie传输。
- Refresh Token(长期,用于续期)必须存在HttpOnly、Secure、SameSite=Strict的Cookie中,且路径限定在/refresh端点,杜绝前端读取。
Access Token:短期有效,直接携带用户身份访问资源。
Refresh Token:长期有效,仅用来换新的Access Token。一旦Access Token过期,客户端用Refresh Token去/refresh换新,整个过程前端无感。
Token的优势:
- 无状态、易扩展:服务器不用存会话,水平扩展没成本,适合微服务、分布式架构。
- 跨域相对友好:前端可以显示设置Authorization 头不需要处理Cookie的域限制。
- 适配度高:Web、App、IoT设备都可以用
- 自包含:Token自身携带用户信息、减少数据库查询。