一 什么是Token?
Token(令牌)在现代软件开发中非常常见,尤其是在涉及认证和授权的系统中。以下是 Token 的主要用处和应用场景:
1. 身份验证 (Authentication)
Token 常用于验证用户的身份,确认用户是否已经通过身份验证。例如:
- 用户在登录时输入用户名和密码,服务器验证成功后生成一个 Token 作为用户的身份凭证。
- 之后,用户的每个请求都会携带这个 Token,服务器可以根据这个 Token 确认用户身份,而不需要每次都重新验证用户名和密码。
2. 授权 (Authorization)
除了身份验证,Token 还常用于确定用户是否有权限访问特定的资源或执行某些操作。例如:
- 基于角色的访问控制(RBAC):Token 中可以包含用户的角色或权限信息,服务器可以根据这些信息决定是否允许用户执行某些操作。
- 访问特定 API 或微服务:在分布式系统中,Token 可以在服务之间传递,用于授权和安全通信。
3. 无状态 (Stateless) 认证机制
Token(尤其是 JWT, JSON Web Token)常用于无状态的认证机制:
- 传统的会话认证(如 Cookie + Session)需要在服务器保存每个用户的会话状态。而使用 Token(如 JWT),所有的用户状态信息都可以编码在 Token 内,服务器只需验证 Token 的有效性即可,极大降低了服务器的负担。
- 这使得系统更易于扩展(Scalable),因为服务器无需保存用户的会话信息,可以轻松实现负载均衡和无状态的微服务架构。
4. 跨平台和跨设备访问
Token 适合用于各种平台和设备的认证场景,比如:
- 移动应用:Token 可以安全地在移动设备上存储,并在每次请求时附带发送。
- 单页面应用 (SPA):前端应用通常在用户登录后获取 Token,并存储在浏览器中(如 LocalStorage 或 SessionStorage)用于后续的 API 调用。
5. API 安全访问
在开放或公开的 API 中,Token 是常见的安全手段之一:
- 使用 OAuth 标准的 Access Token,第三方应用可以安全地访问用户授权的数据。
- 开发者可以通过获取的 Token 访问特定 API,Token 限定了访问的权限和范围。
6. 临时访问权限
在一些场景中,Token 可以用作临时访问凭证,例如:
- 临时文件下载:生成一个短期有效的 Token,允许用户在有限时间内访问文件或资源。
- 重置密码或邮箱验证链接:链接中包含的 Token 通常有时间限制,确保安全性。
7. 安全性
Token 通过以下方式提高安全性:
- 加密和签名:Token 可以使用加密或签名技术防止篡改。即使 Token 被拦截,未经授权的用户也无法轻易伪造或修改 Token。
- 短期有效:Token 的有效期通常较短,过期后即失效,减少了长期 Token 泄露带来的风险。
- 刷新机制:一些系统采用 Refresh Token 机制,Access Token 短期有效,过期后可以通过较长期的 Refresh Token 获取新的 Access Token。
8. 无缝集成和第三方应用
在 OAuth 等协议中,Token 被广泛用于授权第三方应用访问资源:
- 用户可以授权某个应用访问他们在其他平台上的数据,而无需暴露自己的登录凭证。
- 例如,允许一个社交媒体应用获取用户的联系人信息。
典型的 Token 类型:
- JWT(JSON Web Token):常用于无状态的 Web 应用和 API 认证。
- OAuth Access Token:广泛用于第三方应用授权和 API 访问。
- Refresh Token:用于在 Access Token 过期后生成新的 Access Token,减少频繁登录的需求。
总之Token 是一种灵活且广泛使用的认证和授权机制,尤其在现代的分布式系统、微服务架构和前后端分离的应用中。通过 Token,系统可以实现无状态、跨平台、安全且高效的用户身份管理和资源访问控制。
二 token 设计
Token 设计涉及到多个方面,包括其结构、生成方式、安全性、生命周期管理等。一个好的 Token 设计需要兼顾安全性、性能和可扩展性。以下是设计 Token 时需要考虑的几个关键要素:
1. Token 的类型
- JWT (JSON Web Token):这是最常见的 Token 类型,采用 JSON 格式,可以包含用户信息、权限等,此类Token是一串比较长的加密信息,现在开发过程中比较少用。
- 普通 Token:通常是随机生成的字符串,只有服务器知道它的含义。使用这种 Token 时,所有信息都保存在服务器端,客户端仅持有一个引用 ID,长度基本是固定,很多时候直接使用UUID生成,现实开发过程中比较常用,特别是API接口调用基本都用这种类型。
2. Token 的内容设计
- 最小化数据:尽量减少存储在 Token 中的数据,只包含必要的信息。例如用户 ID、角色、权限、Token 的过期时间等。
- 标准化字段:如果使用 JWT,可以利用标准的字段,如
iss
(签发者)、exp
(过期时间)、sub
(主题,如用户 ID)、aud
(受众)。 - 自定义字段:可以添加自定义字段用于业务需求,如
role
、scope
等。
3. Token 的生命周期管理
- 有效期 (Expiration Time, exp):Token 应该设置合理的有效期,以减少安全风险。一般的 Access Token 有效期较短,如 15 分钟或 2 小时。
- Refresh Token 机制:对于长时间保持登录状态的应用,可以使用 Refresh Token。当 Access Token 过期时,通过 Refresh Token 获取新的 Access Token,避免频繁要求用户重新登录。
- Token 的自动失效:设计 Token 时,要考虑如何强制失效特定 Token,比如用户主动登出、修改密码后使旧 Token 失效。
4. Token 的存储
- 浏览器客户端存储:Token 通常存储在浏览器的 LocalStorage、SessionStorage 或 Cookie 中。使用 Cookie 时,应设置
HttpOnly
和Secure
属性以提高安全性。
注意:避免 XSS 和 CSRF 攻击:如果 Token 存储在 LocalStorage 或 SessionStorage,应用需要防范 XSS 攻击;如果存储在 Cookie,需要防范 CSRF 攻击。
- 服务端存储:Token 通常存储在内存或内存数据库,如Redis数据库,很方便设计到期时间,另外保存副本到数据库。
5. Token 的传输
- 使用 HTTPS:Token 传输时都应该使用 HTTPS 以防止被中间人攻击拦截。
- Bearer Token:在 HTTP 请求中,Token 通常作为
Authorization
头的一部分发送,格式为:Authorization: Bearer <token>
。
6. 内容类型的 Token 安全设计
- 签名和加密:使用强健的加密和签名算法,例如 HMAC-SHA256、RSA-SHA256 等。
- 防重放攻击:考虑加入唯一标识符(如
jti
字段)和时间戳来防止重放攻击。 - 权限控制:Token 中包含的权限信息应与服务器进行严格验证,以确保用户只访问其有权访问的资源。
7. Token 的管理与撤销
- 黑名单机制:可以通过维护一个 Token 黑名单或撤销列表,来强制失效某些 Token,特别是在用户登出或发生异常时。
- 状态存储:对于不透明的 Token,服务器可以将其状态存储在数据库或缓存中,允许随时撤销或更新。
8. Token 的兼容性和扩展性
- 多平台支持:确保 Token 在不同平台(Web、移动、桌面)上能够兼容,通常选择标准的 JWT 是一个好方案。
- 灵活的权限模型:设计 Token 时,可以考虑使用权限范围(Scope)或角色(Role)模型,以支持多种业务场景。
9. Token 刷新策略
- 设计 Refresh Token 时,可以使其有效期较长,例如几天到几周,但确保在适当时机刷新,且 Refresh Token 一旦被使用,旧的 Token 应该失效。
三 token 重点(有效期时间计算)
1 token 有效期时间设计和理解 :
Token 的有效期,很多大厂有关 Token 的设计的有效期像都被设置 2 小时。有效期的计算实际就是指从调用接口获取 Token 的时间开始算,而不是指服务器每 2 小时统一更新一次 Token(注意:请不要理解成提供token每两小时更新一次)。
-
Token 有效期从生成时开始计时:当你通过认证接口获取到 Token 时,服务器会记录生成 Token 的时间,并从这一时刻开始计算有效期。如果有效期是 2 小时,那么这个 Token 将在获取后的 2 小时内有效。
-
每次获取的 Token 是独立的:每次调用获取 Token 的接口时,都会返回一个新的 Token,并从生成时刻起重新计时其有效期。这意味着不同用户或不同请求获取的 Token 的有效期开始时间是不同的。
-
Token 到期后需要重新获取:在 2 小时有效期过后,旧的 Token 会失效,客户端需要再次调用接口获取一个新的 Token。
总的来说,文档中提到的 2 小时有效期,是从你成功获取 Token 的时间开始计算的,而不是服务器在固定的时间点批量更新 Token。作为token服务端提供给客户使用时,一定要设计正确的有效期,比如Token设计成服务器本地有效期时(不管客户端是否拿取,服务器内每2 小时更新一个token),可能会造成客户端拿到了token还没有达到设计文档要求的2个小时就失效错误,如果碰巧,还有可能碰刚好客户端拿到Token,Token服务器更新Token,客户端就失效。
2 token 在有效期拿Token细节 :
在有效期内获取新的 Token 时,通常有以下三种常见的处理方式:
1. 新的 Token 和原来的 Token 不一样,旧的 Token 仍然有效
在大多数情况下,新的 Token 和旧的 Token 是不同的,且旧的 Token 在它的有效期内仍然有效。每次生成新的 Token 都会有一个独立的有效期。也就是说,用户在未过期的情况下可以同时持有多个有效的 Token,直到它们各自的有效期结束。
特点:
- 新的 Token 和旧的 Token 都可以使用。
- 系统不会强制使旧的 Token 失效。
- 这种机制常用于简单的系统中,因为它不需要额外的复杂管理。
2. 新的 Token 和原来的 Token 不一样,旧的 Token 失效
在某些高安全性的场景中,系统会选择让旧的 Token 失效。这种设计旨在确保每次只有一个 Token 是有效的。
3. 新的 Token 和原来的 Token 一样
在某些场景中,如请求数据本身自带有身份标识且在加密的情况下,请求Token时只是实现维持时间续时(相当于满血复活)返回先前的Token的同时有效时间重新计算。如果客户持续(未过有效期时间)每次都提前拿Token,那么Token就会持续一致。
开发设计时,还可以参考国内大厂的一些有关token的Api文档设计:
1 蚂蚁集团-支付宝有token的api文档设计如下图:
2 微信有关token 的api文档图如下:
3 南方电网中电联协议有关token的文档
还给了自定义时长,自由度非常大,开发时就要注意把握设计合适的时长了。