联系我们

info@serverion.com

给我们打电话

+1 (302) 380 3902

如何使用 JWT 保护 API

JSON Web Tokens (JWT) 是一种可靠的 API 安全保护方式,它将用户信息直接嵌入到令牌中。它们允许 无状态认证, 这意味着无需服务器端会话存储。这使得它们对于现代分布式系统和微服务而言非常高效。.

关键要点:

  • JWT结构:由三部分组成——标头(元数据)、有效载荷(用户声明)和签名(确保完整性)。.
  • 好处:提高了可扩展性、性能,并简化了访问控制。.
  • 安全最佳实践:

JWT 轻量级、速度快,并且跨平台可用,因此是保护 API 的理想选择。然而,谨慎的实现至关重要,以避免诸如存储或验证不当等常见陷阱。.

如何使用 JSON Web Tokens (JWT) 保护您的 Web API

JWT结构和组成部分

理解 JSON Web Tokens (JWT) 的组成要素是实现安全 API 身份验证的关键。JWT 由三个 Base64Url 编码的部分组成:头部、有效负载和签名。.

JWT 的格式如下所示: 头部.有效载荷.签名. 每个部分分别编码,然后用句点组合起来。这种结构可以实现快速、无状态的令牌验证。.

以下是一个 JWT 示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c 

每个部分在确保令牌的安全性和功能性方面都发挥着特定作用。让我们来详细了解一下。.

头部:令牌类型和算法

标头 包含令牌的元数据,包括令牌类型和用于签名的算法。它是一个小型 JSON 对象,如下所示:

{ "alg": "HS256", "typ": "JWT" } 

"类型" 该字段通常表示该令牌是 JWT,而 "alg" 该字段指定签名算法。算法的选择直接影响代币的安全性。.

  • HS256:依赖于共享密钥,适用于内部服务。.
  • RS256:使用公钥/私钥对,因此非常适合公共 API 和分布式系统。私钥由发行者保管,而验证者只需要公钥。.
  • ES256:在提供强大安全性的同时,计算需求较低,因此非常适合移动应用或低资源环境。.

有效载荷:声明和元数据

有效载荷 实际信息就存储在这里。它包含"声明",即关于用户或其他实体的陈述,以及用于授权的元数据。.

索赔分为三类:

  • 已登记的索赔标准字段,例如 国际空间站 (发行人), 经验值 (到期日), (主题),以及 澳元 (观众)。.
  • 公开声明:在 IANA 公共注册表中注册的自定义字段。.
  • 私人索赔:双方使用 JWT 约定的自定义字段。.

以下是一个有效载荷示例:

{ "sub": "1234567890", "name": "John Doe", "role": "admin", "exp": 1516239022, "iat": 1516235422 } 

需要注意的是,有效载荷是 未加密 它仅经过 Base64Url 编码。这意味着任何人都可以解码并读取其内容。请避免在有效载荷中存储密码或信用卡号等敏感信息。.

妥善管理令牌过期(经验值)和发布时间(iat这对于最大限度降低风险至关重要。例如,在有效负载中嵌入基于角色的数据可以简化本地 API 授权,尤其是在企业环境中。.

签名:令牌完整性

签名 确保令牌的完整性并防止篡改。它的创建方法是:将编码后的头部和有效载荷用句点组合起来,然后使用指定的算法和密钥对结果进行签名。.

为了 HS256, 签名生成方式如下:

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret ) 

为了 RS256, 它使用私钥进行签名,使用公钥进行验证:

RSASHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), privateKey) 

当 API 收到 JWT 时,它会使用令牌的头部和有效负载重新计算签名。如果重新计算的签名与令牌中的签名匹配,则 API 知道令牌未被篡改。例如,如果有人试图更改有效负载(例如,将用户的角色从"用户"升级到"管理员"),则签名验证将失败。这使得 JWT 具有很高的安全性。 防篡改, 确保能够轻松检测到未经授权的修改。.

此外,签名可以确认令牌的来源,为身份验证过程增加一层信任。.

算法 密钥类型 密钥长度 最佳用例
HS256 对称 256 位 内部服务
RS256 不对称 2,048+ 位 公共 API
ES256 不对称 256 位 移动/低资源应用

如何实现 JWT 安全性

使用 JSON Web Tokens (JWT) 保护 API 需要采用结构化的方法进行令牌创建、验证和授权。这包括设置安全的身份验证端点、正确验证令牌以及利用 JWT 声明来管理对资源的访问。.

创建和签署 JWT

第一步是创建一个安全的身份验证服务器,该服务器在验证用户凭据后颁发令牌。登录成功后,服务器会生成一个包含用户信息的 JWT,并使用加密算法对其进行签名。.

以下是一个使用 Node.js 创建和签署 JWT 的示例: jsonwebtoken 图书馆:

const jwt = require('jsonwebtoken'); const token = jwt.sign( { userId: 123, roles: ['admin'] }, process.env.JWT_SECRET, { algorithm: 'HS256', expiresIn: '15m', issuer: 'https://auth.yourapi.com', audience: 'https://api.yourapi.com' } ); 

对于内部服务,, HS256 这是一个不错的选择,因为代币发行者和验证者共享同一个密钥。对于公共 API 或分布式系统而言,, RS256 要么 ES256 它们是更好的选择,因为它们使用公钥-私钥对,允许在不暴露签名密钥的情况下进行令牌验证。.

关键管理最佳实践:

  • 将密钥和私钥安全地存储在环境变量或密钥管理系统中。.
  • 使用强密钥:HMAC 至少 256 位,RSA 至少 2,048 位。.
  • 定期轮换钥匙。.
  • 永远不要将机密信息硬编码到源代码中。.

类似平台 服务器 提供安全的密钥管理和强制HTTPS,支持高性能且安全的API部署。然而,正确的令牌处理实践仍然至关重要。.

令牌创建完成后,下一步是在每个 API 端点验证它们。.

验证 API 中的 JWT

所有需要身份验证的 API 端点都必须验证传入的 JWT,以确认其真实性和完整性。该过程包括提取令牌、验证其签名以及检查其声明。.

以下是一个令牌验证的基本示例:

try { const decoded = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'], audience: 'https://api.yourapi.com', issuer: 'https://auth.yourapi.com' }); } catch (err) { // Token 无效,拒绝请求 } 

验证要点:

  • 到期日(经验值)确保令牌未过期。.
  • 发行人(国际空间站)确认令牌来自您信任的身份验证服务器。.
  • 观众 (澳元)验证令牌是否适用于您的 API。.
  • 签名使用指定的算法验证令牌的完整性。.

如果任何验证步骤失败,则拒绝请求,并返回"无效令牌"之类的通用错误消息,以避免暴露有关验证过程的详细信息。.

设置授权逻辑

令牌验证通过后,即可利用其声明来实施访问控制。JWT 有效负载通常包含用户角色和权限,这有助于确定用户可以访问哪些资源。.

基于角色的访问控制(RBAC): 在创建令牌时,将用户角色添加到令牌有效负载中,并在 API 中间件中检查这些角色,然后再授予对受保护端点的访问权限。以下是一个示例:

function requireRole(requiredRole) { return (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; try { const decoded = jwt.verify(token, process.env.JWT_SECRET); if (decoded.roles && decoded.roles.includes(requiredRole)) { req.user = decoded; next(); } else { res.status(403).json({ error: '权限不足' }); } } catch (err) { res.status(401).json({ error: '无效令牌' }); } }; } 

然后,您可以通过要求特定角色来保护特定路由:

app.get('/admin/users', requireRole('admin'), (req, res) => { // 只有具有管理员角色的用户才能访问此端点 }); 

为了实现更精细的控制,请使用基于权限的授权。在令牌有效负载中包含权限,例如:

""权限": ["读取:用户", "写入:帖子", "删除:评论"] 

然后,检查每项操作所需的权限。.

令牌过期和刷新:

  • 如果访问令牌泄露,应使用较短的有效期(例如 15-30 分钟)以最大程度地降低风险。.
  • 实现刷新令牌以延长会话时间,允许用户无需重复登录即可重新进行身份验证。.

JWT 是无状态的,这意味着您的 API 无需存储会话数据或查询数据库进行身份验证,因此非常适合高流量和分布式系统。这种方法在保证安全性的同时,提高了可扩展性和性能。.

JWT 安全最佳实践

为确保 API 的安全,实施创建、验证和管理 JSON Web Tokens (JWT) 的最佳实践至关重要。这些步骤有助于防止漏洞并保护您的系统。.

使用 HTTPS 进行令牌传输

传输 JWT 时,必须使用 HTTPS。由于 HTTP 标头中的 JWT 是明文,通过不安全的连接发送它们很容易受到中间人攻击而被拦截。这可能导致攻击者未经授权访问您的 API。.

OWASP 2023 年的一份报告显示,超过 60% 个 API 漏洞源于不当的身份验证或不安全的令牌处理,其中许多问题与不安全的传输方法有关。为解决此问题,请遵循以下准则:

  • 启用 SSL/TLS 证书 在所有处理 JWT 身份验证的服务器上。.
  • 将 HTTP 流量重定向到 HTTPS 自动地。.
  • 使用强密码套件 并禁用过时的协议,例如 TLS 1.0 和 1.1。.
  • 设置HTTP严格传输安全(HSTS)标头 防止协议降级攻击。.

对于分布式系统,务必确保所有组件都一致地强制使用 HTTPS。例如,Serverion 在其所有托管解决方案中都强制使用 HTTPS 以维护安全性。.

即使在开发环境中,也应避免通过 HTTP 传输 JWT。忽略这一点可能会导致安全漏洞,这些漏洞可能会蔓延到生产环境中。.

设置令牌过期时间和使用刷新令牌

使用短有效期令牌是一种简单而有效的降低风险的方法。通过将访问令牌的有效期限制在 15-30 分钟,可以减少令牌泄露后攻击者可利用的时间窗口。.

对于较长的会话,请使用刷新令牌。这些令牌的有效期通常为 7-14 天,允许客户端请求新的访问令牌,而无需用户重新进行身份验证。其工作原理如下:

  • 登录后,身份验证服务器会颁发访问令牌和刷新令牌。.
  • 客户端使用有效期较短的访问令牌进行 API 请求。.
  • 当访问令牌过期时,客户端使用刷新令牌获取新的访问令牌,从而在不损害安全性的前提下保持会话连续性。.

MojoAuth 的研究表明,超过 80% 的 API 安全漏洞是由于 API 性能不佳造成的。 令牌管理, 通常情况下,这类攻击会使用有效期很长的令牌,即使令牌被盗用后仍然有效。通过设置令牌过期时间和使用刷新令牌,可以显著降低这些风险。.

安全密钥和秘密管理

JWT 的安全性很大程度上取决于您如何管理签名密钥和密钥。泄露这些密钥——无论是在客户端代码中还是在版本控制系统中——都可能破坏您的整个安全框架。.

存储最佳实践

将签名密钥存储在安全的系统中,例如 AWS Secrets Manager 要么 HashiCorp Vault, 它们提供加密存储、日志记录和自动密钥轮换功能。.

"学习安全存储 PKI 私钥的基本实践,以防止未经授权的访问并确保符合行业标准。"

  • Serverion 博客

主要优势建议

选择强度高、随机生成的密钥,以确保强大的安全性:

  • HS256:使用至少 256 位密钥,非常适合内部服务。.
  • RS256选择 2048 位密钥,最适合公共 API。.
  • ES256:在保证安全性的同时,缩短了密钥长度,使其成为移动应用的绝佳选择。.
算法 安全级别 密钥长度 最佳用例
HS256 高的 256位 内部服务
RS256 非常高 2048 位 公共 API
ES256 非常高 256位 移动应用

关键轮动策略

定期轮换签名密钥以最大程度地降低风险。使用版本控制系统,确保您的应用程序在密钥切换期间能够验证使用当前密钥和先前密钥签名的令牌。这种方法既能保持服务连续性,又能增强安全性。.

避免将密钥直接硬编码到代码库中。而应在运行时安全地注入密钥。.

对于企业级部署,像 Serverion 这样的平台提供安全的基础设施,具有加密存储和强大的访问控制,确保其全球数据中心的密钥管理得当。.

JWT常见错误及解决方法

即使是经验丰富的开发人员,在 JWT 安全方面也可能犯错。为了确保 API 的安全,避免以下常见错误至关重要。这些错误会破坏您辛辛苦苦实施的最佳实践,使您的系统变得脆弱。.

不安全的令牌存储

将 JWT 存储在 localStorage 或 sessionStorage 中存在风险。这些存储方式会使令牌容易受到 XSS(跨站脚本)攻击,攻击者可以利用这些攻击窃取身份验证令牌。.

其工作原理如下:如果攻击者利用了 XSS 漏洞,他们就可以访问存储在这些浏览器存储位置中的任何内容。一旦他们获得了您的 JWT,他们就可以冒充用户,从而未经授权访问受保护的资源。根据 OWASP 2022 年的一份报告,, 超过 30% 的 API 漏洞 这些问题与身份验证和令牌管理不善有关,其中不安全的 JWT 存储是主要原因。.

与其使用 localStorage 或 sessionStorage,不如选择 HttpOnly cookie. 这些 Cookie 无法被 JavaScript 访问,从而显著降低了 XSS 攻击的风险。以下是存储方式的简要比较:

储存方法 安全级别 易受 XSS 攻击 JS 的可访问性 推荐用途
本地存储 低的 高的 不推荐
会话存储 低的 高的 不推荐
HttpOnly Cookie 高的 低的 没有 受到推崇的

对于移动应用,请依赖安全的存储选项,例如 iOS 钥匙串 要么 Android Keystore, 它们为敏感数据提供硬件支持的安全性和加密功能。.

设置 HttpOnly cookie 时,请确保它们也被标记为 安全, 因此,它们只能通过 HTTPS 连接传输。对于企业环境,像 Serverion 这样的供应商提供内置 SSL 管理的托管解决方案,使在您的基础架构中更轻松地实现安全的 Cookie 处理。.

跳过令牌验证

安全存储令牌只是第一步——您还需要对其进行彻底验证。切勿仅仅因为收到了令牌就想当然地认为它有效。.

正确的 JWT 验证包括两个关键步骤: 签名验证索赔核查. 签名确保令牌未被篡改,而声明验证则确认令牌的真实性、有效性以及与您的应用程序的相关性。.

以下是如何在Node.js Express后端实现强大的JWT验证:

const jwt = require('jsonwebtoken'); try { const decoded = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'], audience: 'https://api.example.com', issuer: 'https://auth.example.com' }); req.user = decoded; } catch (err) { return res.status(401).send('无效令牌'); } 

此示例会检查代币的签名、算法、受众和发行方,确保只接受合法代币。务必指定预期算法,以防止攻击者利用算法混淆攻击来钻验证方法的空子。.

拒绝无效令牌时,请使用通用错误消息。这可以防止攻击者利用详细的错误响应来改进其攻击手段。.

将敏感数据放入 JWT 中

JWT 有效负载的内容与存储和验证方式同等重要。切勿在 JWT 有效负载中包含敏感信息。请记住,JWT 有效负载是 编码, 未加密,这意味着任何截获令牌的人都可以轻松解码其内容。.

密码、社保号码或信用卡信息等敏感信息绝不应包含在 JWT 中。如果令牌被拦截、记录或泄露,所有这些数据都将容易受到攻击者的侵害。.

相反,将有效载荷限制为仅 重要信息 授权需要用户 ID、角色和标准声明(例如过期时间)等信息。对于任何其他用户数据,请在令牌验证后单独调用 API,以安全地从服务器检索这些数据。.

为了进一步加强安全性,实施 代币撤销机制 例如使用黑名单来使被盗用的代币失效。使用较短的生命周期(例如,, 15-30分钟) 访问令牌与有效期更长的刷新令牌配对,以最大限度地降低与令牌泄露相关的风险。.

在企业环境中,多个团队和服务可能需要与令牌交互,因此这些实践显得尤为重要。像 Serverion 这样的供应商提供安全的密钥管理和合规性工具,帮助企业在其整个基础架构中维护强大的 JWT 安全性。.

JWT API 安全性的关键点

为了确保 API 安全并保持其功能,实施 JWT 安全性需要采取全面的方法。感谢 无国界性 JWT 在现代分布式系统中运行良好,允许 API 扩展而无需服务器端会话管理。.

你需要重点关注以下几点:

  • 正确验证令牌务必验证 JWT 的签名和核心声明,例如 经验值 (到期日), 国际空间站 (发行人),以及 澳元 (观众)。这确保了令牌的真实性,并且没有被篡改。.
  • 使用短寿命:将访问令牌的有效期缩短,通常为 15-30 分钟,并搭配有效期为 7-14 天的刷新令牌。安全地轮换刷新令牌以降低风险。.
  • 安全传输和存储始终通过 HTTPS 传输令牌,并将其安全地存储在 HttpOnly cookie 等位置,以防止未经授权的访问。.
  • 安全管理钥匙将加密密钥存储在安全的环境中,例如环境变量或专用密钥管理系统,以防止密钥泄露。.
  • 利用索赔进行访问控制使用 JWT 声明可以高效地实现基于角色的访问控制 (RBAC),避免额外的数据库查询。但是,切勿在 JWT 有效负载中包含密码或个人数据等敏感信息,因为 JWT 仅经过编码,并未加密。.

这些实践是构建强大 JWT 安全性的基础。对于处理关键基础设施的组织而言,像 JWT 提供商这样的机构至关重要。 服务器 提供托管解决方案,内置 SSL 证书、安全密钥存储和全球数据中心,以支持安全的 HTTPS 传输和整体基础设施安全。.

常见问题解答

与基于会话的身份验证相比,JWT 如何提升 API 的可扩展性和性能?

JSON Web Tokens (JWT) 提供了一种巧妙的方式来提升 API 的可扩展性和性能,因为它无需服务器端存储会话数据。在传统的基于会话的身份验证中,服务器必须存储会话数据并执行频繁的查找操作,这会消耗大量资源。而 JWT 则不同,它是自包含的——它将所有必需的用户信息都包含在令牌本身中。这意味着服务器的工作量更少,并且由于无需集中式会话存储,因此更容易跨多个服务器进行扩展。.

JWT 的另一个优势在于其轻量级设计,这使得它们可以轻松地通过 HTTP 标头发送。这使其非常适合现代无状态 API 架构。此外,其紧凑的结构和加密签名可确保客户端和服务器之间安全高效的通信,从而有助于保持流畅的性能运行。.

HS256、RS256 和 ES256 在 JWT 签名方面的安全性有何区别?如何为我的 API 选择合适的协议?

您为签署 JSON Web Tokens (JWT) 而选择的算法对您的 API 安全性起着至关重要的作用。. HS256 该方法依赖于共享的密钥进行令牌的签名和验证。这种方法简单直接,但需要谨慎管理密钥以确保安全性。另一方面,, RS256ES256 使用公钥-私钥对,提供额外的安全保障。在这些算法中,私钥专门用于签名,而公钥则用于验证。.

在选择算法时,请考虑 API 的具体需求和配置。如果简单性和速度是首要考虑因素,, HS256 只要密钥得到妥善保护,这可能是一个不错的选择。对于需要更高安全性的系统——尤其是在可以放心共享公钥的分布式环境中—— RS256 要么 ES256 是一个更好的选择。值得注意的是,, ES256 由于采用了椭圆曲线密码学,因此具有代币尺寸更小、加密保护更强大的优势。.

归根结底,关键在于仔细评估您的需求,并遵循管理密钥的最佳实践,以确保您的 API 安全。.

处理令牌过期和刷新令牌的最佳实践是什么,才能在确保安全性的同时,保持流畅的用户体验?

为了有效管理令牌过期和刷新令牌,您需要在确保安全性和保证流畅的用户体验之间找到合适的平衡点。. 访问令牌 为了限制落入不法分子手中可能造成的损害,这些物品的使用寿命应该较短。同时,您可以使用 刷新令牌 当当前访问令牌过期时,系统会自动生成新的访问令牌,从而减少用户重复登录的需要。.

务必以安全的方式存储刷新令牌——使用仅限 HTTP 的 Cookie 是最大限度降低令牌被盗风险的有效方法。此外,建立检测和撤销已泄露令牌的系统也至关重要。这可能包括监控令牌使用模式或维护失效令牌黑名单。将有效期较短的访问令牌与精心管理的刷新令牌相结合,有助于在不给用户带来不便的情况下,保持强大的安全性。.

相关博客文章

zh_CN