第3章 认证与授权基础:、Session、OAuth2、JWT
聊细粒度权限前,得先把地基打牢。
说白了,就是搞明白两个问题:你是谁?你能干什么?
我见过不少团队把认证和授权混着用,结果后面重构时改得头皮发麻。
嗯,咱们一步步来。
3.1 核心概念:认证 vs 授权
先把这个分清楚。
| 概念 | 核心问题 | 生活类比 | 技术例子 |
|---|---|---|---|
| 认证(Authentication) | 你是谁? | 出示身份证 | 登录名+密码,验证通过发 |
| 授权(Authorization) | 你能做什么? | 身份证查出你能否进VIP室 | 里解析出角色,检查是否有读写权限 |
我见过最典型的错误:登录成功后,直接把用户所有数据扔给前端,让前端自己判断能不能点哪个按钮。
这哪是授权?这是裸奔。
3.2 Session 认证:经典的有状态方案
Session,这是最古老也最直观的方式。
原理特别简单:用户登录后,服务端开个房间(Session),房间号(Session ID)交给前端存Cookie。
下次请求带上门牌号,服务端就知道是谁来了。
我在项目中遇到过的一个坑:
一个老系统的Session全存在单台Tomcat内存里。后来业务量上来,搞了负载均衡。
结果用户第一次请求落到A机器,第二次落到B机器,Session丢了。
用户一脸懵,后台疯狂报错。
- 优点:服务端完全可控,踢人、改状态都很方便。
- 缺点:有状态,扩展起来得配Session共享(Redis或数据库),服务器开销大。
别把Session依赖当作默认选项。微服务环境下,Session同步的复杂度会让你很痛苦。
我建议:如果是单体应用,用Session没问题。一旦考虑水平扩展,趁早换方案。
3.3 认证:无状态的主力
说白了就是一张通行证。
用户登录后,服务端签发一个字符串,前端存起来(localStorage或内存),每次请求塞在Header里。
服务端不用存Session,直接验证就能知道用户信息。
为什么我更喜欢?因为它天生适合分布式。
每个服务只要拿到,自己能验,不用回调一个中心节点。省去了Session共享的麻烦。
注意的安全存储。别傻乎乎存Cookie里被XSS扫走。
我个人习惯:Access 存内存,Refresh 存httpOnly Cookie,两个配合用。
3.4 JWT:自包含的规范
JWT是的一种具体实现。
你可以把它理解成一种“自带简历”的——把用户ID、过期时间、角色签名后打包成三段字符串。
结构:Header(算法类型).Payload(用户数据).Signature(防篡改签名)。
// JWT生成示例(Node.js jsonwebtoken库)
const jwt = require('jsonwebtoken');
const payload = { userId: 123, role: 'admin' };
const secret = '你的密钥';
const = jwt.sign(payload, secret, { expiresIn: '1h' });
console.log();
// 输出: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywicm9sZSI6ImFkbWluIiwiaWF0IjoxNzAwMDAwMDAwLCJleHAiOjE3MDAwMDM2MDB9.abc123...
- 优点:无状态、跨语言、信息自包含。
- 缺点:Payload纯文本,敏感数据别放进去;一旦签发,无法主动作废(除非搞个黑名单,那就又变成有状态了)。
我曾经见过把用户密码直接塞JWT Payload里的骚操作。
Base64解码就能看到,这跟把密码贴在脑门上有什么区别?
Payload只放非敏感字段:用户ID、角色、过期时间。
3.5 OAuth2:授权框架,不是认证协议
很多人把OAuth2当成登录方案,不对。
OAuth2是授权框架。它解决的是:第三方应用怎么替用户拿资源。
典型场景:你点“用微信登录”,微信不会把账号密码给网站,而是给个临时令牌,网站拿着令牌去调微信API拿你的昵称头像。
四个角色:
- 资源所有者(用户)
- 客户端(第三方应用)
- 授权服务器(发令牌的地方)
- 资源服务器(存数据的接口)
几种授权模式,我用过实战的就两种:
| 模式 | 适用场景 | 我踩过的坑 |
|---|---|---|
| 授权码模式 | 有后端的Web应用 | 最安全,但流程复杂,得跳转两次 |
| 客户端凭证模式 | 服务端之间通信(M2M) | 没有用户参与,只认应用身份 |
微服务间调用,我经常用OAuth2客户端凭证模式+JWT。
每个服务持有一个Client ID和Secret,去授权服务器换,再用调其他服务。
这样每个接口不用重复鉴权,验一次就行。
3.6 四种机制选型对比
| 机制 | 状态 | 跨域支持 | 安全性 | 复杂度 | 推荐场景 |
|---|---|---|---|---|---|
| Session | 有状态 | 差 | 中 | 低 | 单体系统、传统Web |
| (无状态) | 无状态 | 好 | 中 | 中 | SPA、移动端、分布式 |
| JWT | 无状态 | 好 | 高 | 中 | 微服务、API网关 |
| OAuth2 | 有/无混合 | 优秀 | 高 | 高 | 第三方登录、开放API |
你想想看,你的系统到底需要什么?
如果只是内部系统,用户少且固定,Session够用。
如果是对外API或者跨团队协作,JWT+OAuth2是更稳妥的选择。
我通常给一个实战组合建议:
用户登录走OAuth2授权码模式拿JWT
后续请求带JWT,网关验签,服务间调沿用JWT
需要强时效就配合Refresh 轮换
这样一套下来,认证、授权、安全全占齐。
这张图展示的就是咱们这一章的核心流程。
从用户请求进来,经过API Gateway分流,走到认证服务和授权服务器。
Session负责存状态,JWT负责自验证,OAuth2负责分发。
最后所有请求统一到资源服务器干活。
搞明白这些基础,后面讲细粒度控制你才看得懂。
否则一上来就加密接口、权限下沉,你很容易懵。
嗯,这一章就到这儿。多想想你的业务属于哪种场景,选对方案比调优重要得多。