引言
Bearer Token 认证描述客户端如何向受保护资源提交访问令牌;它不定义令牌格式、登录流程、存储方式或授权策略。令牌可以是 JWT 或不透明引用,有效签名也不能替代 Scope、Tenant、Object 和业务授权。
📋 目录
关键要点
- 什么是 Bearer Token?:Bearer Token 是一种安全令牌,授予持有者(或“承载者”)访问受保护资源的权限。它包含在 HTTP 请求的
Authorization标头中。 - 状态取决于部署:JWT Access Token 可以本地校验,不透明 Token 通常需要 Introspection 或服务端状态。
- JWT 是格式而非权限:JWT 可以携带 Claims,但签名不证明调用者拥有请求中的所有对象。
- 存储取决于场景:浏览器 Cookie、内存 Token 和移动端安全存储分别具有不同的 XSS、CSRF、生命周期和运维取舍。
- 短期 Access Token 只是一个控制项:还需要 Refresh Token 轮换、重放检测、撤销、速率限制和事件响应。
什么是 Bearer Token 认证?
Bearer Token 认证是 RFC 6750 中定义的 HTTP 认证方案。它涉及称为 bearer tokens 的安全令牌,由认证服务器颁发。客户端应用程序在向受保护资源发出请求时,必须在 Authorization 标头中包含此令牌。
GET /api/resource HTTP/1.1
Host: example.com
Authorization: Bearer <token>
“Bearer”表示持有者即可提交该凭据。Resource Server 仍必须执行 Scope、Tenant、Object 和业务策略。
主要特点
- 状态取决于部署:JWT 可以本地验证,不透明 Token 通常需要 Introspection 或服务端状态。
- 可扩展:非常适合分布式系统和微服务架构。
- 广泛支持:与各种协议和框架兼容,包括 OAuth 2.0 和 OpenID Connect。
- 灵活性:可与不同的令牌格式一起使用,例如 JWT(JSON Web Tokens)和不透明令牌。
Bearer Token 的工作原理
Bearer Token 认证的工作流程通常涉及三方:
- 客户端:请求访问受保护资源的应用程序。
- 授权服务器:负责对用户进行身份验证并颁发 bearer token。
- 资源服务器:托管受保护资源的服务器,负责验证令牌。
认证流程
- 用户认证:授权服务器通过适合客户端的流程认证用户,应用不应默认收集用户密码。
- 令牌请求:客户端使用授权结果或客户端凭据交换 Access Token。
- 令牌颁发:授权服务器颁发 Bearer Token,并在适用时颁发 Refresh Token。
- 资源访问:客户端在向资源服务器发出的请求的
Authorization标头中包含 bearer token。 - 令牌验证:Resource Server 校验算法、Issuer、Audience/Resource、Expiry、Not-before、Type、Scope,再执行对象授权。
- 资源响应:只有认证与具体操作策略都通过,Server 才返回资源。
代码示例
JavaScript (Node.js) 与 Passport.js
Passport.js 是 Node.js 流行的认证中间件。passport-jwt 策略简化了 bearer token 的验证。
// 配置 passport-jwt 策略
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt';
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKeyProvider: loadApprovedIssuerKey,
algorithms: ['RS256'], // 示例;应固定 Provider 允许的集合
issuer: process.env.OIDC_ISSUER,
audience: process.env.API_AUDIENCE
};
passport.use(new JwtStrategy(options, async (payload, done) => {
try {
const user = await User.findById(payload.sub);
if (user) {
return done(null, user);
} else {
return done(null, false);
}
} catch (error) {
return done(error, false);
}
}));
// 保护路由
app.get('/profile', passport.authenticate('jwt', { session: false }), (req, res) => {
res.json({ user: req.user });
});
Python 与 Flask-JWT-Extended
把库作为 Resource Server 边界使用;凭据收集和 Token 颁发应由授权系统负责。
# Flask-JWT-Extended Resource Server 边界
import os
from flask import Flask, jsonify
from flask_jwt_extended import jwt_required, JWTManager, get_jwt_identity
app = Flask(__name__)
app.config["JWT_PUBLIC_KEY"] = os.environ["JWT_PUBLIC_KEY"]
app.config["JWT_DECODE_ISSUER"] = os.environ["OIDC_ISSUER"]
app.config["JWT_DECODE_AUDIENCE"] = os.environ["API_AUDIENCE"]
jwt = JWTManager(app)
@app.route("/profile")
@jwt_required()
def profile():
current_user = get_jwt_identity()
# 在此执行 Scope、Tenant、Object 和业务授权。
return jsonify(logged_in_as=current_user), 200
Java 与 Spring Security
Spring Security 为 Java 应用程序中的 bearer token 认证提供了全面的支持。
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public").permitAll()
.anyRequest().authenticated())
.oauth2ResourceServer(oauth -> oauth.jwt());
return http.build();
}
应在配置中固定 Issuer、Audience/Resource、允许算法和 JWKS 来源。认证成功不等于对象授权,服务层仍需执行 Tenant 和 Resource Policy。
安全最佳实践
- Token 颁发和资源请求都必须使用 TLS;客户端应正确校验证书。
- Access Token 应放在
AuthorizationHeader 中,不要放入 Query String、URL、Referer 链接或普通日志。 - 校验 Issuer、Audience/Resource、允许的 Algorithm、签名或 Introspection 结果、Expiry、Not-before、Token Type、Scope 和密钥轮换。
- 将
sub、Scope、Tenant Claim 和 Object ID 作为策略输入,而不是调用者拥有所有对象的证明。 - 浏览器 Cookie 应结合
HttpOnly、合适的SameSite、CSRF Token 或等价请求绑定、Origin 校验和受限 Path;HttpOnly 不能单独防止 CSRF。 - 限制 Access Token 的生命周期和 Scope,对颁发、刷新和资源调用限速,并从 Trace 中脱敏 Token 和敏感 Claim。
Refresh Token 机制
Refresh Token 是独立凭据,不只是寿命更长的 Access Token。稳健实现应在使用时轮换、记录 Token Family、检测重放、设置总过期时间,并在登出或疑似泄露后撤销:
刷新请求
-> 认证 Client 与 Refresh Token Family
-> 拒绝过期、撤销或已使用 Token
-> 原子标记当前 Token 已使用
-> 颁发新的 Access Token 和 Refresh Token
-> 检测重放时撤销整个 Family
具体存储和客户端绑定取决于 OAuth Profile 与应用类型。除非威胁模型明确要求,不要把 Refresh Token 暴露给 JavaScript。
常见问题解答 (FAQ)
1. Bearer Token 和 JWT 有什么区别? Bearer Token 是一种访问令牌。JWT (JSON Web Token) 是创建 Bearer Token 的一种流行格式。虽然大多数 Bearer Token 都是 JWT,但您也可以使用其他格式(如不透明令牌)。
2. 如何在客户端安全地存储 Bearer Token?
Web 应用应根据 XSS/CSRF 威胁模型选择 Cookie Session 或其他存储设计。HttpOnly 只能限制 JavaScript 读取,不能防止 CSRF,因此还需 SameSite 和 CSRF/Origin 控制。移动应用应使用 iOS Keychain、Android Keystore 等系统安全存储。
3. 什么是刷新令牌?为什么它们很重要? Refresh Token 用于获取新的 Access Token,但寿命长本身不是安全收益。应使用轮换、重放检测、过期、安全存储和撤销,否则被盗后可能延长攻击者访问。
4. 如何撤销 Bearer Token? JWT 可能在过期前持续有效,除非 Resource Server 查询撤销状态或采用其他控制。短生命周期、高风险 Token 拒绝列表、密钥轮换和服务端会话/授权检查可以组合使用;不透明 Token 则可通过 Introspection 状态撤销。
5. 我应该使用 HS256 还是 RS256 签名 JWT? 没有一个算法对所有系统都最佳。应根据 Issuer/Resource Server 信任边界、密钥分发、库支持和轮换机制选择经过批准的对称或非对称 Profile,固定算法并拒绝 Algorithm Confusion,不能仅依据 JWT Header 做策略判断。
结论
Bearer Token 认证只是传输约定,不是完整安全架构。可部署的设计还需要明确授权流程、严格 Token 校验、操作级授权、安全存储、Refresh 轮换、撤销和可观测的失败处理。
应固定部署实际测试过的 OAuth/OIDC Profile、库版本、Issuer Metadata 和 Resource Server Policy。周边控制明确且持续验证时,Bearer Token 才能可靠地支撑 API。