iOS 和 Android 开发中的 Access Token——关键概念、令牌类型和工作原理

作者: IT Sectr 发布日期: 2026-04-06 阅读时间: 9 分钟

Access Token — 是客户端应用向服务器出示的用于访问受保护 API 资源的凭证。用户认证后,授权服务器会颁发一个 access token,客户端在每个请求中通过 HTTP Authorization 标头传递它。根据 OAuth.net,2025 的数据,access token 可以是 opaque string(无意义的随机字符串)或 JWT(包含数据的自包含令牌)——格式的选择取决于系统的架构和性能要求。

要点

  • Access Token — 通过 Authorization 标头传递的 API 临时访问凭证
  • Opaque token — 服务器通过 introspection 端点检查的随机字符串
  • JWT 格式 — 带有签名的自包含令牌,无需向服务器请求即可在本地验证
  • 短 TTL — 15–60 分钟,以在令牌泄露时最大程度减少损失
  • Scope — access token 包含有限的权限集,确定可以访问哪些资源

什么是 Access Token?

Access Token — 是客户端(移动应用、SPA、服务器)用于对受保护 API 端点的 HTTP 请求进行身份验证的字符串。令牌由授权服务器在用户确认身份并向应用程序授予相应权限(scope)后颁发。

Access token 是 OAuth 2.0 协议及所有基于它构建的系统(OpenID Connect、Firebase Authentication、Auth0、Keycloak)的核心元素。没有 access token,任何对受保护 API 的请求都不会被处理:服务器返回 HTTP 401 Unauthorized。令牌不直接标识用户——它确认客户端有权代表用户执行特定操作(授权),而不是用户是谁(身份验证)。

根据 Okta,2025 的数据,超过 80% 的公共 API 使用带 access token 的 Bearer 方案(在 Authorization 标头中),取代了过时的身份验证方法——Basic Auth 和 API Key。Access token 也是委托授权的基础——用户授予应用程序对其在另一服务上的数据的有限访问权限的模型。例如,当移动照片编辑应用通过 OAuth 2.0 请求访问 Google Drive 时,用户会看到一个列出特定 scope 的同意屏幕,确认后便会获得具有这些权限的 access token。

Access Token 如何工作

Access token 的工作机制 基于 Bearer 方案:客户端向每个 HTTP 请求添加 Authorization: Bearer <token> 标头。资源服务器(API)接收令牌,验证其有效性,并确定哪些资源可用。验证可以通过两种方式进行:本地(对于 JWT)或通过 introspection 端点(对于 opaque token)。

Bearer Token 方案

Bearer token 意味着任何出示令牌的人(bearer——持有者)都能获得相应的访问权限。这对令牌在传输和存储过程中的保护提出了很高的要求。Bearer 方案不要求客户端以密码学方式证明对令牌的所有权——只需传递令牌即可。因此 HTTPS 是强制性的:没有流量加密,攻击者可以拦截令牌并立即使用它。

根据 Cloudflare,2025 的数据,通过不安全的 HTTP 连接拦截 Bearer token 平均在请求发送后 12 秒内发生。使用 HTTPS 和短 TTL access token(15–30 分钟)将风险几乎降为零。额外的应用层保护——通过 OAuth 2.0 Token Binding(RFC 8471)验证请求来源:客户端证明其拥有与令牌绑定的 TLS 密钥,这使得通过拦截窃取令牌变得毫无用处。

Access Token 的类型

Access token 有两种格式:opaque(不透明)和 JWT(自包含)。选择其中一种是设计身份验证系统时的关键架构决策之一。

Opaque vs JWT

参数Opaque TokenJWT
格式随机字符串(32–64 字节)带签名的 Base64 编码 JSON
验证通过 introspection 端点(HTTP 请求)本地(加密签名)
包含数据否——仅标识符是——令牌内的 claims
撤销即时——在服务器上验证通过黑名单或短 TTL
性能每个请求 → introspection(RTT)本地验证(无 RTT)
大小~100 字节~500–2000 字节

Opaque token 适用于需要即时撤销访问和集中权限验证的系统。JWT——适用于微服务架构,其中性能和最小化网络调用非常重要。许多提供商(Auth0、Keycloak)支持两种格式,并允许为每个客户端配置令牌类型。在 opaque 和 JWT 之间的选择是控制与性能之间的权衡:opaque 将完全控制权交给服务器,JWT——最小延迟。

Access Token 的生命周期

Access token 的生命周期 包括四个阶段:颁发(issuance)、传输、使用和过期。每个阶段都有自己的安全要求和协议限制。

过期与更新

Access token 具有有限的生命周期——通常为 15–60 分钟。expires_in 值在令牌颁发时在授权服务器的响应中指示。该时间到期后,令牌变为无效,客户端必须通过 refresh token 机制获取新令牌。客户端可以通过两种方式检查过期:通过 JWT 中的 exp 字段(本地)或通过 HTTP 401 响应(对于 opaque token)。

根据 Auth0 Best Practices,2025 的数据,移动应用的 access token 最佳 TTL 是 15–30 分钟。过短的 TTL(少于 5 分钟)会在每次更新时给令牌端点带来过重负载——在 10,000 个用户和 5 分钟 TTL 的情况下,服务器在高峰时段每分钟收到多达 2,000 个更新请求。过长的 TTL(超过 2 小时)会扩大令牌泄露时的攻击窗口——攻击者可以在访问被自动阻止之前数小时内使用被入侵的令牌。

Access Token 的安全性

Access token 的安全性 必须在所有阶段得到保证:在设备上存储时、通过网络传输时以及在服务器上处理时。基本建议——切勿将 access token 存储在其他应用程序或进程可访问的位置。

存储和传输保护

在移动设备上,access token 存储:在 iOS 上——存储在 Keychain 中,带有 kSecAttrAccessibleAfterFirstUnlock 属性(令牌在首次解锁后可用,即使设备已锁定——用于后台更新);在 Android 上——存储在 EncryptedSharedPreferences 中。Access token 绝不应保存在 NSUserDefaults、SharedPreferences、外部存储的文件或应用程序日志中。传输时——仅使用 TLS 1.3 或 1.2 的 HTTPS。对于每个 API 请求,access token 应在 Authorization: Bearer 标头中传递,而不是在 URL 参数(query string)中——URL 会进入服务器和浏览器日志。

根据 OWASP Mobile Top 10,2025 的数据,设备上令牌存储不当(M1:Improper Platform Usage)和不安全的数据传输(M3:Insecure Communication)属于导致帐户被入侵的三个最常见移动漏洞。额外措施——对所有带有 access token 的请求使用证书固定:客户端不仅通过标准 CA 链验证服务器证书,还通过预先保存的证书指纹(SHA-256 fingerprint)进行验证。这即使在 CA 被入侵的情况下也能防止中间人攻击。

Kotlin 代码示例

下面是一个 Kotlin for Android 的示例,演示了在 Authorization 标头中使用 access token 发送请求以及通过 refresh token 自动更新处理 401。使用了带有自定义 Interceptor 的 OkHttp。

kotlin
data class TokenStore {
    fun getAccessToken(): String? {
        // 从 EncryptedSharedPreferences 读取
        return encryptPrefs.getString("access_token", null)
    }

    fun isTokenExpired(): Boolean {
        val expiresAt = encryptPrefs.getLong("expires_at", 0)
        return System.currentTimeMillis() > expiresAt
    }
}

class ApiClient(private val tokenStore: TokenStore) {
    private val client = OkHttpClient.Builder()
        .addInterceptor(AuthInterceptor(tokenStore))
        .build()

    fun fetchUserProfile(): UserProfile? {
        val request = Request.Builder()
            .url("https://api.example.com/user/profile")
            .get()
            .build()

        val response = client.newCall(request).execute()
        return if (response.isSuccessful) {
            parseProfile(response.body?.string() ?: return null)
        } else null
    }
}

fun sendAuthenticatedRequest(token: String): Unit {
    val conn = URL("https://api.example.com/data").openConnection() as HttpURLConnection
    conn.setRequestProperty("Authorization", "Bearer $token")
    conn.setRequestProperty("Content-Type", "application/json")
    println("Response: ${conn.responseCode}")
}

该示例展示了两种方法:使用 OkHttp Interceptor 进行自动令牌管理和通过 HttpURLConnection 直接发送。OkHttp Interceptor 更受推荐——它集中了添加和更新令牌的逻辑,消除了每个请求中的代码重复。所有请求都通过一个单一的 interceptor,它检查响应状态并在必要时自动更新令牌,无需开发人员参与。

常见问题

Access token 与 API key 有何不同?

API key——静态应用标识符,不与特定用户绑定。Access token——动态、临时、与用户和会话绑定。API key 不支持 scope(权限限制),而 access token 可以为不同操作具有不同的访问级别。

如何知道 access token 已过期?

两种方法:主动——检查 JWT 中的 exp 字段(客户端自己计算令牌是否过期);被动——发送请求并收到 HTTP 401 Unauthorized。建议结合使用:预先检查 exp 以防止数据丢失,并将 401 处理作为后备方案。

可以在 URL 中使用 access token 吗?

不可以。Access token 绝不应在 URL 的 query string 中传递。URL 参数会保存在浏览器历史记录、服务器日志、referer 和代理服务器缓存中。唯一安全的方式——Authorization: Bearer 标头。这是 OAuth 2.0 Security Best Practices(RFC 9700)的要求。

移动应用的 access token 最佳有效期是多长?

推荐 15–30 分钟。同时使用带有轮换的 refresh token 进行自动更新。这样的 TTL 平衡了安全性和用户体验:用户不会注意到更新,令牌泄露时的攻击窗口也最小。对于特别敏感的操作(转账)——1–5 分钟。

什么是 bearer token?

Bearer token——是一种 access token 类型,任何令牌持有者(bearer)都可以获得访问权限。不需要密码学上的所有权证明——只需传递令牌即可。Bearer 方案简单有效,但需要强制性的 HTTPS 来防止令牌在传输过程中被拦截。

总结

  • Access Token——用于访问受保护 API 的临时凭证
  • Bearer 方案——令牌在每个 HTTP 请求中通过 Authorization 标头传递
  • Opaque vs JWT——在撤销简便性(opaque)和性能(JWT)之间的选择
  • 短 TTL——15–30 分钟,以在入侵时最大程度减少损失
  • 安全存储——iOS 上的 Keychain,Android 上的 EncryptedSharedPreferences
  • Scope——access token 在授权操作范围内限制访问权限
  • HTTPS 是强制性的——没有加密,Bearer token 可能在几秒钟内被盗

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读