接口安全概述:认证、授权、审计
做接口安全这么多年,我最深的体会是:安全不是加一把锁,而是一整套规则。你想想看,一个对外暴露的 API,每天几百上千万次调用,里面混着爬虫、恶意扫描、甚至数据盗取。怎么防?
说白了,就三个环节:认证、授权、审计。我习惯把它们叫做“接口安全的三道门”。
为什么这三件事必须分开?
我在项目中遇到过不少同学,把认证和授权混在一起搞。比如登录时顺便把用户角色塞进 ,然后直接用角色判断权限。看似省事,但你想想看——角色变了怎么办? 还没过期,旧权限还在用。这就是典型的边界没划清。
还有一种情况:接口只检查了 是否合法(认证),没检查这个用户有没有权限调用(授权)。结果普通用户通过抓包,直接调了管理员接口。嗯,很常见。
所以,三道门必须独立设计,逐一实现。下面我们一个一个来说。
认证(Authentication):确认身份
认证就是问:你谁啊?
常见的认证方式有这些:
| 认证方式 | 典型实现 | 安全性 | 适用场景 |
|---|---|---|---|
| HTTP Basic Auth | 用户名:密码 base64 | 低(明文传输,需配合 HTTPS) | 内部工具、调试接口 |
| / JWT | 服务端签发 ,客户端携带 | 中(注意签名算法和过期时间) | RESTful API、移动端 |
| OAuth2.0 | 授权码流程、客户端凭证 | 高(标准协议,支持第三方) | 开放平台、跨系统授权 |
| + Secret | 请求签名(HMAC) | 中高(防重放需加时间戳) | 服务端到服务端调用 |
授权(Authorization):控制行为
认证通过了,接下来问:你有资格做这件事吗?
授权需要依赖权限模型,最常见的就是我们这门课的核心 —— RBAC(基于角色的访问控制)。但这里先不展开 RBAC 的细节,我们先讲清楚授权的职责:
- 根据用户身份,查询角色 / 权限列表
- 判断当前请求的资源 + 操作,是否在权限范围内
- 如果不在,直接返回 403 Forbidden
我曾经遇到一个坑:开发同学在授权逻辑里直接硬编码了“管理员角色 ID=1”。结果后来业务调整,角色表重排,ID 变了,管理员访问不了后台。嗯,从那时起我再也不在代码里写死角色 ID。
审计(Audit):留下痕迹
最后一道门,也是最容易被忽略的一道门:审计。
认证和授权都过了,用户正常访问接口。但你得知道:谁在什么时候做了什么操作?传了什么参数?结果成功还是失败?
审计要记录的关键字段,我一般这样设计:
| 字段 | 说明 | 示例 |
|---|---|---|
| user_id | 操作者标识 | 12345 |
| action | 操作类型 | DELETE |
| resource | 操作对象 | /api/users/678 |
| result | 执行结果 | success / fail |
| ip | 来源 IP | 192.168.1.1 |
| timestamp | 操作时间 | 2025-03-20T10:30:00Z |
| request_body | 请求参数(敏感信息脱敏) | { "name": "***" } |
你可能觉得审计就是个日志,用不上。但真遇到安全事件(比如数据泄露),审计日志就是唯一的破案线索。我在项目中见过一个案例:攻击者通过 SQL 注入拿到了管理员 ,公司因为没审计日志,花了三天才定位到漏洞入口。
三者关系图
下面这张图展示了认证、授权、审计在接口请求中的完整流程:
从上图可以看出:所有请求先经过认证,认证通过后进入授权判断。如果授权失败直接返回 403,不再继续;如果授权成功,则执行接口逻辑,同时审计模块记录操作明细。
我的一些避坑建议
- 认证和授权不能复用同样的代码路径。我曾经见过一个项目,认证和授权写在一个 filter 里,导致异常时既未正确身份校验,又遗漏了权限检查。
- 审计日志不要只记录成功。失败的认证和授权同样要记 —— 它们是安全事件的前兆。
- 注意敏感信息脱敏。审计日志里如果记录了明文密码或 ,那就变成新的安全漏洞了。
- 授权失败不返回具体原因。你想想看,如果告诉用户“你没有删除权限”,攻击者就知道你的权限模型里有“删除”这个动作。统一返回 403 即可。