• 在微服务架构中使用JWT


    本文展示了如何使用 JWT 进行跨服务认证/授权。

    在单体架构中,所有子系统都在一个应用程序中:身份验证和授权、会话管理器、业务逻辑等。如果我们在谈论微服务架构,有些事情变得更加复杂。

    微服务

    微服务架构中,通常,认证/授权是一个单独的服务。
    在这里插入图片描述
    要请求服务,您必须首先进行身份验证并获取访问令牌。 一个示例是 OAuth 2.0 客户端凭据流。 要获取令牌,您需要传递 client idclient secret。 在下面的示例中,凭据作为 Authorization Basic 标头传递:

    POST /token HTTP/1.1
    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=client_credentials
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    响应此请求,我们将获得一个访问令牌,可用于请求所需的服务。 但是我们如何在服务端验证这个令牌呢?

    验证

    最明显的方法是查询授权服务并自省令牌。 但是当我们的系统包含数百个服务时,这样的请求会给授权服务带来很大的负担,并且有时会成为瓶颈。 为避免这种情况,我们可以在服务中验证令牌。 为此,我们可以使用自包含令牌,其中包括 JWT(JSON Web 令牌)。

    JWT是某种token,一般由headerbodysignature三部分组成。 该标准在 RFC7519 中有更详细的描述。
    在这里插入图片描述
    这里 header 指定:

    • typ – 一种令牌类型(我们正在考虑JWT)
    • alg – 签名算法(例如 HS256 – 带有 SHA-256 的 HMAC(标头 + 有效负载 + 密钥))
    • kid – 当有多个密钥时使用,您需要了解哪个密钥是已签名的令牌

    body 由标准标记和自定义标记组成:

    • iss – 发行人(发行令牌的人)
    • aud – 观众(令牌的对象)
    • iat – 合适签发
    • exp – 过期时间
    • sub – 主题
    • jti – JWT唯一ID

    对称(例如,HS256)和非对称(例如,RS256)签名算法都可以用作签名。 在对称算法中,只有一个私钥,用于签名和验证。 在 非对称算法 中,签名者使用只有他自己保留的私钥,并验证 可以使用可以分发给每个人的公钥来完成签名。

    事实证明,这样的签名令牌是自给自足的,不能在接收方不注意的情况下被操纵。 接收方收到token后,可以验证签名,确保token没有被修改。 这意味着令牌内的所有数据都可以信任。 这消除了通过调用远程服务来内省令牌的需要,从而减少了服务的负载。
    在这里插入图片描述
    如果服务 B 收到一个包含访问令牌的请求,它需要一个密钥来验证签名。 如果我们有一个包含几十上百个微服务的复杂系统,那么必要的服务就需要分发这个密钥。 如果使用对称算法,密钥很可能会泄漏。 拥有私钥,您可以签署任何内容的令牌。 因此,强烈建议使用非对称算法。 在这种情况下,通常会在身份验证/授权服务上放置一个端点,该服务返回一个用于检查签名的公钥列表。 必要的服务需要自己查询和缓存这些键。 使用这种方法,很容易组织密钥轮换——在某个时刻,auth-service 可以生成一组新的密钥并开始使用它。 接收到这样一个新令牌后,接收服务无法自行找到缓存的密钥,将再次请求 auth-service 并接收更新的密钥列表。

    例子:

    curl https://www.googleapis.com/oauth2/v3/certs
    
    {
      "keys": [
        {
          "alg": "RS256",
          "kty": "RSA",
          "use": "sig",
          "n": "4DauU23AEpgBg3zJbqT8Fn-Zf817ru1moUjG75yJ-T0NpuQiggrXPn2YoKgo_qtnYloZh-RLjFfRv_Jb47riZhV5vsW7PiMR4MjlXgMWQlWG7kD9cIH5cTzBuEAzCkZZDu7XFkTfWUtRdWS5iKBjfQ465Qi5yFqfh7iHbQoKiN32pkWDI4MG8CUQC-YDbz77IRMpD39ZzNxkxYqbeJ226MrgKVGHFbmZLZPX8VX4r45NZifkPHa5-G5YDxaL622fkTqgPkyJtFOMy08X6K4BtVV0ZUJqi19bzEW970aI13seu0BzBsIspZ2NSPtljQqQFJTcW1EAmOCB5iNDi3J0mQ",
          "e": "AQAB",
          "kid": "fda1066453dc9dc3dd933a41ea57da3ef242b0f7"
        },
        {
          "e": "AQAB",
          "alg": "RS256",
          "n": "yJdNun_DT8_krjOUFMk4UPb7KgOyoN2EIHVL77LFLUlzFwOLon1pEceYcWffNQnjdtzDCN5-q6DxlIiJyDgQhPPMpJzMcpZceo0tKd-Ve1RLEUVcbnbjyZ-inrxVWfYTOuWTsutt7EylFDIMfw1Dh14IccFG5loyLdtZX2yejhXmJzMCxTISE_lCxCIiIqu5filfc3AnnyNb66Mv_oyK5z22pc9f-dFAmT3e5IXA-0UkrEVtLl7lRGmWdBkAkEWzhh17aQ0BynxpcTX5efGyr2b5ktUObCNdKMwNE4_Berz4l7_Oz6-gWDlyjbROrHKx0B27SFHdtNHbYARJsfVsjw",
          "kty": "RSA",
          "kid": "1727b6b49402b9cf95be4e8fd38aa7e7c11644b1",
          "use": "sig"
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    验证令牌签名后,我们必须检查 issaud 声明。 iss 必须包含身份验证服务的标识符或 URL。 aud 包含为其生成令牌的服务的标识符或标识符列表。 我们必须确保我们的系统出现在这个列表中,并且这个令牌是为我们准备的。

    在所有检查之后,我们可以授权请求并执行必要的操作。

    令牌撤销

    重要的是要注意,自包含令牌的问题之一是无法简单地撤销它们。 例如,一个令牌被泄露,我们需要禁止它在我们系统中的所有服务上使用。 但我们的服务只进行签名验证——令牌仍然有效。

    在这种情况下,我们会缩短令牌的生命周期(分钟),之后它将不再有效。 但是如果这还不够,并且需要立即撤销令牌,您可以使用令牌黑名单作为键值存储库,它将存储被撤销令牌的 ID (jti)。 然后每个服务都应该查询该存储并确保令牌不在列表中。 没有必要将令牌永久存储在此存储库中,而只是在我们达到令牌中的 exp 值之前。 此外,令牌撤销事件本身非常少见,因此存储空间会很小且会被读取。

    敏感的信息

    应该理解,令牌的内容没有加密,令牌的正文是可以读取的。 如果您必须将令牌提供给第三方服务,那么您应该小心放入令牌正文中的数据。 但如果需要该数据,您可以使用加密版本的令牌 (JWE)。 另一种方法是不给出完整的令牌,而只给出它的标识符(jti),将jti——完整的令牌映射存储在存储库/缓存中。 在下一个请求中,将 jti 交换为完整令牌并在系统内使用完整令牌。

    总结

    在跨服务身份验证/授权实现中正确使用 JWT 可以让我们构建灵活、安全、高负载的应用程序。 了解它的工作原理将减少在构建系统架构时引入漏洞的可能性。

  • 相关阅读:
    c++11 入门基础
    HTTP和HTTPS的区别是什么
    JAVA注解_概述、内置注解、Retention、Target、Documented、Inherited
    Redis常见错误
    业务数据分析-Excel必须掌握的7个操作技巧(二)
    incarnation flashback database 时可以 offline 不符合的 datafile
    ubuntu14.04 AR5B22 无线网卡连不上 AP 问题解决
    C++ 模板进阶使用
    Java学习到面试所遇的小小问题
    C++(Qt)软件调试---linux使用dmesg定位程序崩溃位置(14)
  • 原文地址:https://blog.csdn.net/wjw465150/article/details/126698988