JWT 身份验证插件

Solr 可以使用 JWTAuthPlugin 支持基于 JSON Web Token (JWT) 的 Bearer 身份验证。

这允许 Solr 通过验证由身份提供者以数字方式签名的 JWT 格式的 访问令牌 来断言用户已通过外部 身份提供者 进行身份验证。典型用例是将 Solr 与启用了 OpenID Connect 的 IdP 集成。

模块

这通过 jwt-auth Solr 模块 提供,在使用前需要启用该模块。

启用 JWT 身份验证

要使用 JWT Bearer 身份验证,security.json 文件必须包含一个 authentication 部分,该部分定义用于身份验证的类以及配置参数。

用于在没有配置的情况下注册插件的最简单的 security.json

{
  "authentication": {
    "class":"solr.JWTAuthPlugin",
    "blockUnknown":"false"
  }
}

该插件默认情况下要求所有流量都提供有效的 JWT 令牌。

如果 blockUnknown 属性设置为 false(如上例所示),则可以使用未经身份验证的 REST API 调用开始配置插件,这在 编辑 JWT 身份验证插件配置 部分中有进一步描述。

配置参数

密钥 说明 默认值

blockUnknown

如果需要通过 REST API 执行配置,或者如果使用授权插件并且只想保护特定路径,则设置为 false。默认情况下,所有请求都需要令牌

true

realm

在 HTTP 401 响应中回显的身份验证域的名称。还将显示在管理 UI 登录页面中

'solr-jwt'

scope

有效范围的空格分隔列表。如果已配置,JWT 访问令牌必须包含一个 scope 声明,其中至少包含一个列出的范围。示例:solr:read solr:admin

requireIss

失败的请求缺少 iss(发布者)声明

true

requireExp

失败的请求缺少 exp(到期时间)声明

true

algAllowlist

JSON 数组,其中包含要接受的算法:HS256HS384HS512RS256RS384RS512ES256ES384ES512PS256PS384PS512、`none

默认允许所有算法

jwkCacheDur

JWK 缓存的持续时间(以秒为单位)

3600(1 小时)

principalClaim

从哪个声明 ID 中提取主体

sub

rolesClaim

从哪个声明 ID 中提取用户角色。支持顶级声明和嵌套声明。使用 someClaim.child 语法来寻址嵌套在 someClaim 对象中的声明 child。然后,该声明必须包含空格分隔的角色列表或 JSON 数组。然后,这些角色可用于在授权插件中定义细粒度的访问权限

默认情况下,scope 声明中的范围作为用户角色传递

claimsMatch

必须与正则表达式(值)匹配的声明(键)的 JSON 对象。示例:{ "foo" : "A|B" } 将要求 foo 声明为“A”或“B”。

adminUiScope

定义从管理 UI 登录时请求的范围

如果未定义,则使用 scope 参数中的第一个范围

redirectUris

外部身份验证后重定向的有效位置。采用字符串或字符串数组。必须是 Solr 的基本 URL,例如 https://solr1.example.com:8983/solr/,并且必须与事先在身份提供程序中注册的重定向 URI 列表匹配。

默认为空列表,即假设任何节点都是有效的重定向目标。

trustedCerts

与 IdP 通信时应受信任的一个或多个 X.509 SSL 证书,采用纯文本 PEM 或 PKCS#7 格式。换行符必须替换为 \n。有关其用法,请参阅段落 信任 IdP 服务器

默认为 Java 信任库

trustedCertsFile

包含一个或多个 X.509 SSL 证书的 PEM、DER 或 PKCS#7 类型文件的路径,在与 IdP 通信时应信任这些证书。还可以是文件路径数组。有关其用法,请参阅信任 IdP 服务器段落。

默认为 Java 信任库

issuers

要支持的发行者(身份提供者)列表。有关配置语法,请参阅发行者配置部分

发行者配置

此插件支持一个或多个令牌发行者(IdP)。发行者在issuers配置键下配置为 JSON 对象列表。列表中的第一个发行者是“主要发行者”,它用于登录到管理 UI。

密钥 说明 默认值

name

发行者的唯一名称。用于通过 API 操作列表。

wellKnownUrl

指向OpenID Connect Discovery端点的 URL

clientId

用于 OpenID Connect 的客户端标识符。需要使用管理 UI 进行身份验证。仅适用于主要发行者

jwksUrl

指向JWK端点的 URL。必须使用 https 协议。或者,也可以使用 URL 数组,在这种情况下,在验证签名时将参考所有 URL 中的所有公钥。

如果提供了wellKnownUrl,则自动配置

jwk

作为jwksUrl的替代方案,您可以提供一个包含发行者公钥的静态 JSON 对象。格式为 JWK 或 JWK 集,有关示例,请参阅RFC7517

iss

在 IdP 上配置的唯一发行者 ID。传入令牌必须具有匹配的iss声明。还用于在配置了多个发行者时解析发行者。

如果提供了wellKnownUrl,则自动配置

aud

验证aud(受众)声明是否等于此字符串

如果已配置,则使用clientId

authorizationEndpoint

Id 提供者授权端点的 URL

如果提供了wellKnownUrl,则自动配置

tokenEndpoint

Id 提供者令牌端点的 URL

如果提供了wellKnownUrl,则自动配置

authorizationFlow

指定要使用的 OAuth 2.0 流程。支持的流程为“implicit”和“code_pkce”(用于带有“Proof Key for Code Exchange”的授权码)。注意:“implicit”已弃用,强烈建议改用“code_pkce”。

implicit

为了向后兼容,主要发行者的所有配置键都可以配置为顶级键,name除外。

更多配置示例

使用 JWKS URL

要开始对所有用户强制执行身份验证,要求在 Authorization 头中提供有效的 JWT,您需要使用一个或多个 JSON Web Key(JWK)来配置插件。这是一份包含用于对 JWT 进行签名/加密的密钥的 JSON 文档。它可以是对称密钥或非对称密钥。JWK 可以从外部 HTTPS 端点获取(并缓存)或直接在 security.json 中指定。以下是一个前者的示例

{
  "authentication": {
    "class": "solr.JWTAuthPlugin",
    "jwksUrl": "https://my.key.server/jwk.json"
  }
}

使用 Admin UI 支持

此示例显示了使用 OpenID Connect Discovery 的配置,其中有一个众所周知的 URI,用于自动配置许多常见设置,包括使用具有 OpenID Connect 启用的身份提供程序的 Admin UI 的能力。

{
  "authentication": {
    "class": "solr.JWTAuthPlugin",
    "wellKnownUrl": "https://idp.example.com/.well-known/openid-configuration",
    "clientId": "xyz",
    "redirectUris": "https://my.solr.server:8983/solr/"
  }
}

在这种情况下,jwksUrlissauthorizationEndpoint 将从获取的配置中自动配置。

复杂示例

我们来看一个更复杂的配置,这次配置了两个颁发者,其中一个使用静态嵌入式 JWK

{
  "authentication": {
    "class": "solr.JWTAuthPlugin", (1)
    "blockUnknown": true, (2)
    "principalClaim": "solruid", (3)
    "claimsMatch": { "foo" : "A|B", "dept" : "IT" }, (4)
    "scope": "solr:read solr:write solr:admin", (5)
    "algAllowlist" : [ "RS256", "RS384", "RS512" ], (6)
    "issuers": [ (7)
      {
        "name": "example1-static", (8)
        "jwk": { (9)
          "e": "AQAB",
          "kid": "k1",
          "kty": "RSA",
          "n": "3ZF6w....vjbCXxw"
        },
        "clientId": "solr-client-12345", (10)
        "iss": "https://example.com/idp", (11)
        "aud": "https://example.com/solr" (12)
      },
      {
        "name": "example2",
        "wellKnownUrl": "https://example2.com/.well-known/oidc", (13)
        "aud": "https://example2.com/solr"
      }
    ],
    "trustedCertsFile": "/path/to/certsFile.pem" (14)
  }
}

我们来评论一下此配置

1 插件类
2 确保阻止任何没有有效令牌的人(这也是默认设置)
3 从默认 sub 以外的另一个声明中获取用户 ID
4 要求 roles 声明为“A”或“B”之一,并且 dept 声明为“IT”
5 要求范围 solr:readsolr:writesolr:admin 之一
6 仅接受用于签名的 RSA 算法
7 颁发者配置数组
8 每个颁发者对象都应具有唯一名称
9 在这里,我们以内联方式传递 JWK,而不是使用 jwksUrl 引用 URL
10 设置在身份提供程序中注册的客户端 ID
11 配置颁发者 ID。将用于验证令牌。令牌的“iss”声明必须与配置的颁发者 ID 之一匹配。
12 配置受众声明。令牌的“aud”声明必须与配置的颁发者之一的“aud”匹配。
13 此颁发者通过发现自动配置,因此不需要“iss”和 JWK 设置
14 提供 SSL 证书以信任 IdP https 通信。

使用非 SSL URL

在生产环境中,您应始终使用 SSL 保护的 HTTPS 连接,否则您会面临攻击风险。但是,在开发中,使用常规 HTTP URL 并绕过 Solr 执行的安全检查可能很有用。为了支持这一点,您可以在启动时设置系统属性 -Dsolr.auth.jwt.allowOutboundHttp=true

信任 IdP 服务器

与 Oauth2 服务器(IdP)的所有通信都通过 HTTPS 进行。默认情况下,使用 Java 的内置 TrustStore。但是,通过配置选项 trustedCertsFiletrustedCerts 之一,该插件将相反信任所提供的证书集,而不是由根 CA 签名的任何证书。这既更安全,也允许您信任自签名证书。即使 Solr 未在 SSL 模式下启动,它也有好处。

请配置 trustedCertstrustedCertsFile 选项。配置两者将导致错误。如果 trustedCertsFile 是一个字符串数组,Solr 将解析所有文件中的证书。

多个身份验证方案

Solr 提供了 MultiAuthPlugin 来支持基于 Authorization 标头的多个身份验证方案。这允许您将 Solr 配置为使用 JWTAuthPlugin 将用户管理和身份验证委派给 OIDC 提供程序,但还允许一小部分服务帐户在不支持或不实用 OIDC 时使用 Basic 身份验证。

编辑 JWT 身份验证插件配置

上面提到的所有属性都可以使用 身份验证 API 进行设置或更改。因此,您可以从仅配置 classblockUnknown=false 的简单配置开始,然后使用 API 配置其余部分。

设置配置属性

为身份验证插件设置属性。上表中的每个配置键都可以用作 set-property 命令的参数键。

示例

V1 API

curl http://localhost:8983/solr/admin/authentication -H 'Content-type:application/json' -H 'Authorization: Bearer xxx.yyy.zzz' -d '{
  "set-property": {
    "blockUnknown":true,
    "wellKnownUrl": "https://example.com/.well-known/openid-configuration",
    "scope": "solr:read solr:write"
  }
}
'

V2 API

curl http://localhost:8983/api/cluster/security/authentication -H 'Content-type:application/json' -H 'Authorization: Bearer xxx.yyy.zzz' -d '{
  "set-property": {
    "blockUnknown":true,
    "wellKnownUrl": "https://example.com/.well-known/openid-configuration",
    "scope": "solr:read solr:write"
  }
}
'

在插件处于活动状态后,插入一个有效的 JWT 访问令牌(紧凑序列化格式,如上文中的 xxx.yyy.zzz)以使用 Solr 进行身份验证,或将 blockUnknown=false 保留到配置完成,然后将其切换为 true 以开始强制执行。

目前不支持通过 REST API 添加多个令牌颁发者,但是您可以通过使用“颁发者”属性作为顶级属性通过 API 配置单个颁发者来解决此问题。

使用带有 JWT 身份验证的客户端

SolrJ

SolrJ 目前不支持按请求提供 JWT 令牌。

cURL

要使用 cURL 实用程序对 Solr 进行身份验证,请在 Authorization 标头中提供一个有效的 JWT 访问令牌,如下所示(将 xxxxxx.xxxxxx.xxxxxx 替换为您的 JWT 紧凑令牌)

curl -H "Authorization: Bearer xxxxxx.xxxxxx.xxxxxx" http://localhost:8983/solr/admin/info/system

管理 UI

启用此插件后,用户在尝试执行受限操作后将被重定向到管理 UI 中的登录页面。该页面有一个按钮,用户将单击该按钮并被重定向到身份提供商的登录页面。

如果配置了多个颁发者 (IdP),列表中的第一个将用于管理 UI。经过身份验证后,用户将被重定向回 Solr 管理 UI,返回到上次已知的位置。会话将持续到 JWT 令牌到期时间,并且仅对一个 Solr 服务器有效。这意味着在导航到另一个 Solr 节点时,您必须重新登录。在左栏中还有一个注销菜单,用户可以在其中明确注销。

使用 Solr 控制脚本和 JWT 身份验证

控制脚本 (bin/solr) 目前不支持 JWT 身份验证。