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 数组:HS256HS384HS512RS256RS384RS512ES256ES384ES512PS256PS384PS512none

默认值是允许所有算法

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

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

默认为 Java 信任库。

trustedCertsFile

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

默认为 Java 信任库。

issuers

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

发行者配置

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

描述 默认值

name

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

wellKnownUrl

指向 OpenID Connect Discovery 端点的 URL。

clientId

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

jwksUrl

指向 JWKs 端点的 URL。必须使用 https 协议。可以选择 URL 数组,在这种情况下,验证签名时将参考来自所有 URL 的所有公钥。

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

jwk

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

iss

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

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

aud

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

如果配置了 clientId,则使用它。

authorizationEndpoint

Id 提供商的授权端点的 URL。

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

tokenEndpoint

Id 提供商的令牌端点的 URL。

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

authorizationFlow

指定要使用的 OAuth 2.0 流。支持的流有“implicit”和“code_pkce”(用于具有“代码交换证明密钥”的授权码)。注意:“implicit”已弃用,强烈建议改用“code_pkce”。

implicit

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

更多配置示例

使用 JWKS URL

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

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

支持管理 UI

此示例显示了使用 OpenID Connect Discovery 的配置,其中包含一个众所周知的 URI,用于自动配置许多常见设置,包括使用启用 OpenID Connect 的身份提供商使用管理 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 的内置信任库。但是,通过配置选项 trustedCertsFiletrustedCerts 之一,插件将 改为 信任所提供的一组证书,而不是任何由根 CA 签名的证书。这既更安全,也允许您信任自签名证书。它还具有即使 Solr 未在 SSL 模式下启动也能工作的优点。

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

多种身份验证方案

Solr 提供 MultiAuthPlugin 以支持基于 Authorization 标头的多种身份验证方案。这允许您配置 Solr 使用 JWTAuthPlugin 将用户管理和身份验证委托给 OIDC 提供商,还允许一小部分服务帐户在不支持或不方便使用 OIDC 时使用 Basic 身份验证。

编辑 JWT 身份验证插件配置

可以使用 身份验证 API 设置或更改上述所有属性。因此,您可以从仅配置了 classblockUnknown=false 的简单配置开始,然后使用 API 配置其余配置。

设置配置属性

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

示例

  • V1 API

  • V2 API

curl https://127.0.0.1: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"
  }
}
'
curl https://127.0.0.1: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"
  }
}
'

一旦插件激活,请插入紧凑序列化格式 (xxx.yyy.zzz 以上) 的有效 JWT 访问令牌以使用 Solr 进行身份验证,或者在配置完成之前保留 blockUnknown=false,然后将其切换为 true 以开始强制执行。

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

将客户端与 JWT 身份验证一起使用

SolrJ

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

cURL

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

curl -H "Authorization: Bearer xxxxxx.xxxxxx.xxxxxx" https://127.0.0.1:8983/solr/admin/info/system

管理 UI

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

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

将 Solr 控制脚本与 JWT 身份验证一起使用

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