2. 认证机制基础
聊特征平台的安全,第一个绕不开的就是认证。说白了,就是证明「你是你」的过程。
我见过不少团队,花大把精力搞权限模型,结果认证环节漏了个口子。嗯,那权限做得再精细也没用。今天我们就从最基础的密码认证开始,一路讲到 OAuth 2.0,把认证的核心逻辑理清楚。
认证 vs 授权:别搞混了
先纠正一个常见的误区。很多人把认证和授权混着说,其实它们是两码事。
| 概念 | 英文 | 核心问题 | 打个比方 |
|---|---|---|---|
| 认证 | Authentication | 你是谁? | 进小区大门刷门禁卡 |
| 授权 | Authorization | 你能做什么? | 刷完卡,能不能进 18 楼 CEO 办公室 |
认证是授权的前提。门都进不来,谈什么权限?我在做特征平台时,第一步就是把认证层单独抽出来,跟业务逻辑解耦。这样后面换认证方式,不会动到核心代码。
密码认证:最古老也最脆弱
用户名+密码,这招用了快五十年了。简单直接,但坑也最多。
我接手过一个遗留系统,密码直接明文存数据库。当时我整个人都不好了。正确的做法是什么?
- 不能存明文密码。数据库被拖库,用户密码全裸奔。
- 必须加盐哈希。用 bcrypt、scrypt 或 Argon2,别自己造轮子。
- 限制登录频率。防止暴力破解。
核心原则:服务端只存密码的哈希值,永远不存原始密码。用户输入的密码,经过同样的哈希运算后比对结果。
我曾经在一个项目里见过有人用 MD5 哈希密码。嗯,那玩意儿跑个彩虹表,几秒钟就破出来了。后来我强制团队全部迁移到 bcrypt,虽然计算慢一点,但安全多了。
Session-Cookie:有状态认证的经典方案
密码验证通过后,怎么让服务器记住你?Session-Cookie 模式是传统 Web 应用的标准答案。
流程很简单:
- 用户登录,服务器验证密码。
- 服务器创建一个 Session,存到内存或 Redis 里。
- 服务器把 Session ID 通过 Cookie 返回给浏览器。
- 后续请求,浏览器自动带上 Cookie,服务器查 Session 确认身份。
我的建议:Session 一定要设置过期时间。我见过有人把 Session 有效期设成 30 天,结果员工离职了,账号还能用。一般 30 分钟无操作就过期比较合理。
但 Session-Cookie 有个硬伤——它是有状态的。服务器得存 Session 数据。如果做微服务,每个服务都得去共享 Session 存储,复杂度就上来了。
JWT:无状态认证的利器
后来大家发现,能不能让 自己携带用户信息?这样服务器就不用存 Session 了。JWT(JSON Web )就是干这个的。
JWT 长这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
它分成三部分:Header、Payload、Signature。用 Base64 编码,最后用密钥签名。服务器收到 JWT,验签通过就直接从 Payload 里拿用户信息,不用查数据库。
注意:JWT 的 Payload 只是 Base64 编码,不是加密。里面不要放敏感信息,比如密码、身份证号。我见过有人把用户手机号直接放 JWT 里,解码就能看到,这很危险。
JWT 的好处是无状态,适合微服务和移动端。但坏处是签发后不能主动失效。你想踢掉一个用户?除非改密钥,否则做不到。所以 JWT 的过期时间要设短一点,配合 Refresh 使用。
OAuth 2.0:授权框架,不是认证协议
很多人把 OAuth 2.0 当成认证协议,其实它是个授权框架。它的核心是让第三方应用在用户授权下,有限度地访问资源。
举个例子:你的特征平台想接入用户的 GitHub 仓库数据。你不想把 GitHub 密码给特征平台吧?OAuth 2.0 就是解决这个问题的。
OAuth 2.0 有四种授权模式,最常用的是授权码模式:
- 用户点击「使用 GitHub 登录」。
- 浏览器跳转到 GitHub 授权页面。
- 用户同意授权。
- GitHub 返回一个授权码给回调地址。
- 特征平台后端用授权码去 GitHub 换 Access 。
- 之后用 Access 访问 GitHub API。
关键点:Access 是给第三方应用的,不是给用户的。它代表了用户的授权,但本身不包含用户身份信息。要获取用户信息,需要用 Access 去调用用户信息接口。
我做过一个特征平台,用 OAuth 2.0 对接了多个数据源。踩过一个坑:Access 过期了,没有自动刷新机制,导致数据同步任务半夜全挂了。后来加了 Refresh 和自动重试,才算稳定。
OAuth 2.0 与 OpenID Connect
OAuth 2.0 只负责授权,不负责认证。那怎么知道用户是谁?OpenID Connect(OIDC)就是在 OAuth 2.0 之上加了一层身份认证。
OIDC 在 OAuth 2.0 的基础上,增加了一个 ID (JWT 格式),里面包含了用户的身份信息。这样你既拿到了授权,又知道了用户是谁。
| 协议 | 产出物 | 用途 |
|---|---|---|
| OAuth 2.0 | Access | 访问资源 |
| OpenID Connect | ID + Access | 身份认证 + 资源访问 |
现在大部分企业级认证方案,比如 Keycloak、Auth0、Azure AD,底层都是 OAuth 2.0 + OIDC。如果你要自建认证服务,建议直接上 OIDC,别自己再封装一层。
认证机制的核心逻辑
说了这么多,其实认证机制的核心逻辑就三条:
- 凭证验证:你拿什么证明你是谁?密码、短信验证码、生物特征、第三方 。
- 会话管理:验证通过后,怎么维持登录状态?Session、JWT、。
- 凭证存储:服务端怎么安全地存凭证?哈希、加盐、加密。
下面这张图,把认证机制的整体脉络画出来了:
特征平台选型建议
回到特征平台的场景,我个人的选型经验是这样的:
- 内部平台:用 OAuth 2.0 + OIDC 对接公司统一认证(LDAP、AD、SSO)。别自己写登录页,直接用 Keycloak 或类似方案。
- 对外 API:用 JWT 做无状态认证,配合 做机器对机器的调用。
- 混合场景:JWT 做用户认证,OAuth 2.0 做第三方集成授权。
避坑指南:我曾经在一个特征平台里同时用了 Session 和 JWT,结果 Session 过期了 JWT 还没过期,导致权限校验逻辑混乱。后来统一成 JWT + Refresh ,逻辑清晰多了。
认证是安全的基石。选对方案,后面权限管控才能站得住脚。下一层,我们就要聊授权模型了——怎么控制「你能做什么」。