安全架构
摘要
第 1 章 Quarkus 安全架构 复制链接链接已复制到粘贴板!
Quarkus 安全架构提供了几个内置身份验证机制,并高度自定义。在 Quarkus 中保护 HTTP 应用的主要机制是 HttpAuthenticationMechanism 接口。
1.1. Quarkus 安全架构概述 复制链接链接已复制到粘贴板!
当客户端发送 HTTP 请求时,Quarkus 安全通过与几个内置核心组件交互来编配安全身份验证和授权,包括 HttpAuthenticationMechanism、IdentityProvider 和 SecurityIdentityAugmentor。
顺序安全验证过程会产生三个结果之一:
- HTTP 请求经过身份验证和授权,并被授予对 Quarkus 应用的访问权限。
-
HTTP 请求身份验证失败,请求者会收到特定于身份验证机制的质询,例如:
401错误、重新验证 URL 重定向或某些其他自定义身份验证质询响应。有关质询响应的实际示例,请参阅 Quarkus 安全提示和 Tricks 指南。 - HTTP 请求授权失败,请求者被拒绝访问 Quarkus 应用。
下图显示了 Quarkus 安全架构的详细流程的步骤:
图 1.1. Quarkus 安全架构和进程流
1.2. Quarkus 安全架构的核心组件 复制链接链接已复制到粘贴板!
1.2.1. HttpAuthenticationMechanism 复制链接链接已复制到粘贴板!
quarkus Security 使用 HttpAuthenticationMechanism 从 HTTP 请求中提取身份验证凭据,并将它们委派给 IdentityProvider,以将凭据转换为 SecurityIdentity。例如,凭据可以来自 Authorization 标头、客户端 HTTPS 证书或 Cookie。
当 Quarkus 安全拒绝身份验证请求时,HttpAuthenticationMechanism 会向客户端返回身份验证质询。质询类型取决于身份验证机制。例如,使用 OIDC OpenID Connect (OIDC)授权代码流机制,会生成一个重定向 URL,客户端将返回到 OpenID Connect 供应商进行验证。
1.2.2. IdentityProvider 复制链接链接已复制到粘贴板!
IdentityProvider 验证身份验证凭据,并将它们映射到 SecurityIdentity,后者具有用户名、角色、原始身份验证凭据和其他属性。
您可以为每个经过身份验证的用户注入 SecurityIdentity 实例,以获取经过身份验证的身份信息。
在其他上下文中,可以具有与其他相同信息或部分的并行表示,例如,用于 Jakarta REST 的 SecurityContext 或 JSON Web 令牌(JWT)的 JsonWebToken。
如需更多信息,请参阅 Quarkus 身份提供程序 指南。
1.2.3. SecurityIdentityAugmentor 复制链接链接已复制到粘贴板!
由于 Quarkus Security 是自定义的,例如,您可以将授权角色添加到 SecurityIdentity 中,然后注册并排列一个或多个 SecurityAugmentor 实现。
注册的 SecurityIdentityAugmentor 实例会在安全身份验证过程的最终阶段调用。如需更多信息,请参阅 "Security Tips and Tricks" 指南中的 Security Identity Customization 部分。
1.3. 支持的验证机制 复制链接链接已复制到粘贴板!
Quarkus 安全框架支持多种身份验证机制,也可以组合使用。一些支持的身份验证机制内置在 Quarkus 中,另一些则要求您添加扩展名。
要了解 Quarkus 中的安全身份验证以及支持的机制和协议,请参阅 Quarkus 指南中的 Quarkus 身份验证机制。
1.4. 主动验证 复制链接链接已复制到粘贴板!
主动验证在 Quarkus 中默认启用。如果传入请求具有凭证,即使目标页面不需要身份验证,请求也会被验证。如需更多信息,请参阅 Quarkus 主动身份验证 指南。
1.5. Quarkus 安全自定义 复制链接链接已复制到粘贴板!
Quarkus Security 可自定义。您可以自定义 Quarkus 的以下核心安全组件:
-
HttpAuthenticationMechanism -
IdentityProvider -
SecurityidentityAugmentor
有关自定义 Quarkus 安全性的更多信息,包括被动安全性以及如何注册安全供应商,请参阅 Quarkus 安全提示和技巧 指南。
1.6. 参考 复制链接链接已复制到粘贴板!
第 2 章 Quarkus 中的验证机制 复制链接链接已复制到粘贴板!
Quarkus 安全框架支持多种身份验证机制,您可以使用它们来保护应用程序。您还可以组合身份验证机制。
在选择用于保护 Quarkus 应用程序的身份验证机制前,请查看提供的信息。
2.1. 支持的身份验证机制概述 复制链接链接已复制到粘贴板!
一些支持的身份验证机制内置在 Quarkus 中,另一些则要求您添加扩展名。所有这些机制都包括在以下部分中:
下表将特定的身份验证要求映射到您可以在 Quarkus 中使用的支持机制:
| 身份验证要求 | 身份验证机制 |
|---|---|
| 用户名和密码 | |
| bearer 访问令牌 | |
| 单点登录(SSO) | |
| 客户端证书 |
如需更多信息,请参阅以下 令牌身份验证机制比较 表。
2.2. 内置身份验证机制 复制链接链接已复制到粘贴板!
Quarkus Security 提供以下内置身份验证支持:
2.2.1. 基本身份验证(Basic authentication) 复制链接链接已复制到粘贴板!
您可以使用内置 HTTP 基本身份验证机制保护 Quarkus 应用程序端点。如需更多信息,请参阅以下文档:
2.2.2. 基于表单的身份验证 复制链接链接已复制到粘贴板!
Quarkus 提供基于表单的身份验证,它们的工作方式类似于传统的 Servlet 形式的身份验证。与传统的形式身份验证不同,经过身份验证的用户不会存储在 HTTP 会话中,因为 Quarkus 不支持集群的 HTTP 会话。相反,身份验证信息存储在加密的 Cookie 中,可由共享同一加密密钥的所有群集成员读取。
要应用加密,请添加 quarkus.http.auth.session.encryption-key 属性,并确保您设置的值至少为 16 个字符。加密密钥使用 SHA-256 进行哈希处理。生成的摘要用作 Cookie 值的 AES-256 加密的密钥。Cookie 包含作为加密值的一部分的到期时间,因此集群中的所有节点都必须同步其时钟。在一分钟的间隔内,如果会话正在使用,则会使用更新的到期时间生成新的 Cookie。
要开始使用表单身份验证,您应该有类似的设置,如 启用基本身份验证和属性 quarkus.http.auth.form.enabled 所述,必须设置为 true。
带有表单验证的简单 application.properties 类似如下:
在 application.properties 文件中配置用户名、secret 和角色只适用于测试场景。对于保护生产应用,使用数据库或 LDAP 存储此信息至关重要。如需更多信息,您可以查看 带有 Jakarta Persistence 的 Quarkus 安全性,或其他 启用基本身份验证 中所述。
应用程序登录页面将包含类似如下的 HTML 表单:
使用单页应用程序(SPA),您通常希望通过删除默认页面路径来避免重定向,如下例所示:
现在,您已为 SPA 禁用了重定向,您必须以编程方式从客户端登录并注销。以下是登录 j_security_check 端点的 JavaScript 方法示例,并通过销毁 Cookie 来注销应用。
要从客户端注销 SPA,cookie 必须设为 quarkus.http.auth.form.http-only-cookie=false,以便您可以销毁 Cookie,并可能重定向到您的主页。
要从服务器注销 SPA,cookie 可以设置为 quarkus.http.auth.form.http-only-cookie=true,并使用此示例代码销毁 Cookie。
- 1
- 通过删除会话 Cookie 来执行注销。
2.2.2.1. 基于表单的身份验证配置参考 复制链接链接已复制到粘贴板!
以下属性可用于配置基于表单的身份验证:
build 时修复的 :在构建时修复的配置属性 - 所有其他配置属性在运行时可覆盖
| 配置属性 | Type | default |
|
确定是否启用整个权限集。 默认情况下,如果定义了权限集,则会启用它。
环境变量: | 布尔值 | |
|
此权限集链接到的 HTTP 策略。 有三个内置策略:allow、deny 和 authenticated。可以定义基于角色的策略,扩展可以添加自己的策略。
环境变量: | string | 所需的 HEKETI Required |
|
此权限集的方法应用到。如果没有设置,则适用于所有方法。 请注意,如果请求与任何权限集中的任何路径匹配,但由于未列出方法,则请求将被拒绝。 方法特定权限优先于未设置任何方法的匹配项。 这意味着,如果 Quarkus 配置为允许 GET 和 POST 请求到 /admin,且没有将其他权限配置为 /admin 将被拒绝。
环境变量: | 字符串列表 | |
|
此权限检查应用到的路径。如果路径以 86] 结尾,则这被视为路径前缀,否则它将被视为完全匹配。 匹配会以长度为基础完成,因此最具体的路径匹配具有优先权。 如果多个权限集与同一路径匹配,那么显式方法匹配优先于设置方法,否则应用最严格的权限。
环境变量: | 字符串列表 | |
|
必须用来验证用户身份的路径特定身份验证机制。它需要匹配
环境变量: | string | |
|
表示除了具有获奖路径的策略外,此策略还始终适用于匹配的路径。避免创建多个共享策略,以最大程度降低性能影响。
环境变量: | 布尔值 |
|
|
权限检查是否应该应用到所有匹配路径,还是专用于 Jakarta REST 资源的路径。
环境变量: | All :适用于所有匹配路径。
jaxrs: Declares,权限检查必须仅应用于 Jakarta REST 请求路径。使用这个选项,延迟权限检查是否使用匹配的 Jakarta REST 端点上的注解选择验证机制。如果使用以下 REST 端点注解,则必须设置这个选项:- | all |
|
允许访问此策略保护的资源的角色。默认情况下,任何经过身份验证的用户都允许访问。
环境变量: | 字符串列表 |
|
|
根据
环境变量: | Map<String,List<String>> | |
|
如果成功应用此策略,则授予
环境变量: | Map<String,List<String>> | |
|
此策略授予的权限将通过此配置属性指定的
环境变量: | string |
|
|
将
例如,如果
环境变量: | Map<String,List<String>> | |
|
客户端证书属性,其值将根据证书属性文件中指定的角色映射映射到"安全Identity"角色。属性必须是 Relative Distinguished Names (RDN)或 Subject Alternative Names (SAN)之一。默认情况下,通用名称(CN)属性值用于角色映射。支持的值有:
环境变量: | string |
|
|
包含客户端证书属性值到角色映射的属性文件。只有在使用
属性文件预期具有
环境变量: | path | |
|
身份验证域
环境变量: | string | |
|
登录页面。可以通过设置
环境变量: | string |
|
|
用户名字段名称。
环境变量: | string |
|
|
密码字段名称。
环境变量: | string |
|
|
错误页面。可以通过设置
环境变量: | string |
|
|
如果没有保存的页面要重定向到,则要重定向到的登录页面。可以通过设置
环境变量: | string |
|
|
选项控制用于将用户重新定向到他们要访问的位置的 Cookie 名称。
环境变量: | string |
|
|
不活跃(空闲)超时 当达到不活跃超时时,cookie 不会更新,并会强制使用新的登录。
环境变量: |
| |
|
Cookie 在新的 Cookie 被更新超时替代之前如何获得,也称为"renewal-timeout"。 请注意,较小的值会导致服务器负载稍多(因为新加密的 Cookie 将更频繁生成);但是,较大的值会影响不活动超时,因为在生成 Cookie 时设置了超时。 例如,如果这设为 10 分钟,并且不活跃超时为 30m,如果用户的最后一个请求为 9m,则实际超时将在最后一次请求后发生 21m,因为仅在生成新 Cookie 时超时才会刷新。 也就是说,在服务器端不会跟踪超时;时间戳采用 Cookie 本身进行编码和加密,并通过每个请求进行解密和解析。
环境变量: |
| |
|
用于存储持久会话的 Cookie
环境变量: | string |
|
|
会话和位置 Cookie 的 Cookie 路径。
环境变量: | string |
|
|
Cookie 域参数值(如果设置了)将用于会话和位置 Cookie。
环境变量: | string | |
|
设置 HttpOnly 属性,以防止通过 JavaScript 访问 Cookie。
环境变量: | 布尔值 |
|
|
会话和位置 Cookie 的 SameSite 属性。
环境变量: |
|
|
|
会话 Cookie 的 max-Age 属性。这是浏览器将保留 Cookie 的时间。 默认值为空,这意味着 Cookie 将保留,直到浏览器关闭为止。
环境变量: | ||
|
后位置。
环境变量: | string |
|
|
要求所有注册的 HTTP 身份验证机制都必须尝试验证请求凭据。
默认情况下,当 所有生成的安全身份都可以使用以下工具的方法检索: `io.quarkus.vertx.http.runtime.security.HttpSecurityUtils++#++getSecurityIdentities(io.quarkus.security.identity.SecurityIdentity)`
注入的
此属性默认为 false,这意味着当创建第一个 如果启用了特定于路径的身份验证,则此属性将被忽略。
环境变量: | 布尔值 |
|
|
包含的身份验证模式。
环境变量: | lax: 如果至少有一个注册的 HTTP 身份验证机制创建了身份,则身份验证会成功。
严格 :如果所有注册的 HTTP 身份验证机制都创建身份,则身份验证成功。通常,当凭证通过 mTLS 执行时,包含的身份验证应该处于严格的模式,当 mTLS 和另一个身份验证(如 OIDC bearer 令牌身份验证)时,必须成功。在这种情况下,由第一个机制 mTLS 创建的 | strict |
要写入持续时间值,请使用标准 java.time.Duration 格式。如需更多信息,请参阅 Duration#parse ()Java API 文档。
您还可以使用简化的格式,从数字开始:
- 如果值只是一个数字,它代表时间(以秒为单位)。
-
如果值为数字,后跟
ms,代表时间(毫秒)。
在其他情况下,简化的格式被转换为 java.time.Duration 格式以进行解析:
-
如果该值是一个数字,后跟
h、m或s,则前缀为PT。 -
如果值为数字,后跟
d,则会以P为前缀。
2.2.2.2. 以编程方式设置基于表单的身份验证 复制链接链接已复制到粘贴板!
除了 基于 Form 的身份验证配置参考部分中列出的配置 属性外,Quarkus 在运行时支持程序设置,如下例所示:
- 1
- 观察
io.quarkus.vertx.http.security.HttpSecurityCDI 事件,并以编程方式配置 Form 身份验证机制。
2.2.3. 双向 TLS 身份验证 复制链接链接已复制到粘贴板!
Quarkus 提供 mutual TLS (mTLS)身份验证,以便您可以根据其 X.509 证书验证用户。
要使用此验证方法,您必须首先为应用程序启用 SSL/TLS。如需更多信息,请参阅 Quarkus "HTTP 参考" 指南中的支持使用 SSL/TLS 的安全连接 部分。
在应用程序接受安全连接后,下一步是使用保存应用程序信任的所有证书的 quarkus.http.ssl.certificate.trust-store-file 属性配置 quarkus.http.ssl.certificate.trust-store-file 属性。此文件还包含有关当客户端(如浏览器或其他服务)如何请求证书的信息,请尝试访问受保护的资源之一。
因为 JKS 不再是 Quarkus 中的默认密钥存储和信任存储格式,因此框架会根据文件扩展名进行 educated guess:
-
.pem、.crt和.key显示为 PEM 证书和密钥。 -
.jks、.keystore、和.truststore显示为 JKS 密钥存储和信任存储。 -
.p12、.pkcs12和.pfx显示为 PKCS12 密钥存储和信任存储。
如果您的文件没有使用其中一个扩展,则必须使用以下属性设置格式:
quarkus.http.ssl.certificate.key-store-file-type=JKS # or P12 or PEM quarkus.http.ssl.certificate.trust-store-file-type=JKS # or P12 or PEM
quarkus.http.ssl.certificate.key-store-file-type=JKS # or P12 or PEM
quarkus.http.ssl.certificate.trust-store-file-type=JKS # or P12 or PEM
JKS 变得不常使用。从 Java 9 开始,Java 的默认密钥存储格式是 PKCS12。JKS 和 PKCS12 之间的显著区别在于 JKS 是特定于 Java 的格式。相反,PKCS12 是一种标准化、不中立的方式,用于存储加密的私钥和证书。
以下是启用 mTLS 的示例配置:
当传入请求与信任存储中的有效证书匹配时,您的应用程序可以通过注入 SecurityIdentity 获取主题,如下所示:
获取主题
您还可以使用以下示例中介绍的代码获取证书:
获取证书
import java.security.cert.X509Certificate; import io.quarkus.security.credential.CertificateCredential; CertificateCredential credential = identity.getCredential(CertificateCredential.class); X509Certificate certificate = credential.getCertificate();
import java.security.cert.X509Certificate;
import io.quarkus.security.credential.CertificateCredential;
CertificateCredential credential = identity.getCredential(CertificateCredential.class);
X509Certificate certificate = credential.getCertificate();
2.2.3.1. 将证书属性映射到角色 复制链接链接已复制到粘贴板!
来自客户端证书的信息可用于将角色添加到 Quarkus 安全Identity 。
在检查客户端证书的通用名称(CN)属性后,您可以将新角色添加到 SecurityIdentity 中。添加新角色的最简单方法是将证书属性用于角色映射功能。
例如,您可以更新部分中显示的属性,它引入了 Mutual TLS 身份验证,如下所示:
根据前面的配置,如果客户端证书的 CN 属性等于 alice 或 bob,如果请求等同于 jdoe,则请求被授权。
2.2.3.2. 使用证书属性来增强 SecurityIdentity 复制链接链接已复制到粘贴板!
如果 角色选项的自动映射证书属性不适用,则始终可以注册 SecurityIdentityAugmentor。自定义 SecurityIdentityAugmentor 可以检查不同的客户端证书属性的值,并相应地增强 SecurityIdentity。
有关自定义安全身份的更多信息,请参阅 Quarkus " 安全提示 和 tricks" 指南中的 安全身份自定义 部分。
2.2.3.3. 以编程方式设置 mutual TLS 客户端身份验证 复制链接链接已复制到粘贴板!
在 Mutual TLS 身份验证 部分中,我们在 application.properties 文件中配置 mutual TLS 客户端身份验证,如下所示:
io.quarkus.vertx.http.security.HttpSecurity CDI 事件允许您以编程方式配置 mutual TLS 身份验证,如下例所示:
TLS 配置示例
双向 TLS 客户端身份验证配置示例
- 1
- 启用并需要 mutual TLS 客户端身份验证,并将
tls-config-1TLS 配置用于 HTTP 服务器 TLS 通信。tls-config-1TLS 配置在 TLS registry 中注册。
也可以将证书属性映射到角色。让我们考虑在 Mapping certificate 属性到 roles 部分所解释的示例:
带有编程集的配置类似如下:
此 API 还允许您使用证书来增强 SecurityIdentity :
quarkus.http.tls-configuration-name=tls-config-1 quarkus.tls.tls-config-1.key-store.p12.path=server-keystore.p12 quarkus.tls.tls-config-1.key-store.p12.password=the_key_store_secret quarkus.tls.tls-config-1.trust-store.p12.path=server-truststore.jks quarkus.tls.tls-config-1.trust-store.p12.password=the_trust_store_secret
quarkus.http.tls-configuration-name=tls-config-1
quarkus.tls.tls-config-1.key-store.p12.path=server-keystore.p12
quarkus.tls.tls-config-1.key-store.p12.password=the_key_store_secret
quarkus.tls.tls-config-1.trust-store.p12.path=server-truststore.jks
quarkus.tls.tls-config-1.trust-store.p12.password=the_trust_store_secret
- 1
- 在 Using certificate attributes to increased SecurityIdentity 部分中,我们提到了
SecurityIdentityAugmentor可用于将客户端证书属性值映射到SecurityIdentity角色。MTLSAPI 允许您定义这样的角色映射。
如果 Quarkus 在启动失败后以 DEV 模式启动 HTTP 服务器,Quarkus 可能需要回退到 application.properties 文件中提供的配置。这是一个已知的限制。
2.3. 其他支持的身份验证机制 复制链接链接已复制到粘贴板!
Quarkus 安全还通过扩展支持以下身份验证机制:
2.3.1. OpenID Connect 身份验证 复制链接链接已复制到粘贴板!
OpenID Connect (OIDC)是一个身份层,可在 OAuth 2.0 协议之上工作。OIDC 允许客户端应用程序根据 OIDC 供应商执行的身份验证验证用户身份,并检索有关该用户的基本信息。
Quarkus quarkus-oidc 扩展提供了一个被动、可互操作的、启用了多租户的 OIDC 适配器,它支持 Bearer 令牌和授权代码流身份验证机制。Bearer 令牌身份验证机制从 HTTP Authorization 标头中提取令牌。
授权代码流机制将用户重定向到 OIDC 供应商,以验证用户身份。用户重定向到 Quarkus 后,机制通过交换为 ID、访问和刷新令牌授予的提供代码,从而完成身份验证过程。
您可以使用可刷新的 JSON Web 密钥(JWK)设置或远程内省它们,以验证 ID 和访问 JSON Web Token (JWT)令牌。但是,不透明(也称为二进制令牌)只能远程内省。
使用 Quarkus OIDC 扩展,Bearer 令牌和授权代码流身份验证机制都使用 SmallRye JWT 身份验证来将 JWT 令牌表示为 MicroProfile JWT org.eclipse.microprofile.jwt.JsonWebToken。
2.3.1.1. 用于 OIDC 身份验证的其他 Quarkus 资源 复制链接链接已复制到粘贴板!
有关可用于保护 Quarkus 应用程序的 OIDC 身份验证和授权方法的更多信息,请参阅以下资源:
| OIDC 主题 | Quarkus 信息资源 |
|---|---|
| bearer 令牌身份验证机制 | |
| 授权代码流身份验证机制 | |
| OIDC 和 SAML 身份代理 | |
| 多个租户,可以支持 Bearer 令牌身份验证或授权代码流机制 | |
| 使用常用的 OpenID Connect 供应商保护 Quarkus | |
| 使用 Keycloak 集中管理授权 |
要在运行时启用 Quarkus OIDC 扩展,请在构建时设置 quarkus.oidc.tenant-enabled=false。然后,使用系统属性在运行时重新启用它。
有关在多租户 OIDC 部署中管理单个租户配置的更多信息,请参阅"使用 OpenID Connect (OIDC)多租户"指南中的 禁用 租户配置部分。
2.3.1.2. OpenID Connect 客户端和过滤器 复制链接链接已复制到粘贴板!
quarkus-oidc-client 扩展为从支持以下令牌授予的 OpenID Connect 和 OAuth2 供应商中获取和刷新访问令牌提供 OidcClient :
-
client-credentials -
password -
refresh_token
quarkus-resteasy-client-oidc-filter 扩展需要 quarkus-oidc-client 扩展。它提供 JAX-RS RESTful Web Services OidcClientRequestFilter,它将 OidcClient 获取的访问令牌设置为 HTTP Authorization 标头的 Bearer 方案值。此过滤器可以注册到注入当前 Quarkus 端点中的 MicroProfile REST 客户端实施,但它与此服务端点的身份验证要求无关。例如,它可以是公共端点,也可以使用 mTLS 进行保护。
在这种情况下,您不需要使用 Quarkus OpenID Connect 适配器来保护 Quarkus 端点。
quarkus-resteasy-client-oidc-token-propagation 扩展需要 quarkus-oidc 扩展。它提供 Jakarta REST TokenCredentialRequestFilter,它将 OpenID Connect Bearer 令牌或 Authorization Code Flow 访问令牌设置为 HTTP Authorization 标头的 Bearer scheme 值。此过滤器可以注册到注入当前 Quarkus 端点中的 MicroProfile REST 客户端实现,该端点必须使用 Quarkus OIDC 适配器进行保护。此过滤器可以将访问令牌传播到下游服务。
如需更多信息,请参阅 OpenID Connect 客户端和令牌传播快速启动 和 OpenID Connect (OIDC)和 OAuth2 客户端和过滤器参考指南。
2.3.2. smallrye JWT 身份验证 复制链接链接已复制到粘贴板!
quarkus-smallrye-jwt 扩展提供 MicroProfile JSON Web Token (JWT) 2.1 实施,以及多个选项来验证已签名和加密的 JWT 令牌。它将它们表示为 org.eclipse.microprofile.jwt.JsonWebToken。
quarkus-smallrye-jwt 是 quarkus-oidc Bearer 令牌身份验证机制的替代选择,并使用 Privacy Enhanced Mail (PEM)密钥或可刷新的 JWK 密钥集来验证仅 JWT 令牌。quarkus-smallrye-jwt 还提供 JWT 生成 API,您可以使用它来轻松创建 经过签名、内部 签名的,以及 加密的 JWT 令牌。
如需更多信息,请参阅使用 JWT RBAC 指南。
2.4. 在 OpenID Connect 和 SmallRye JWT 身份验证机制之间进行选择 复制链接链接已复制到粘贴板!
使用以下信息来选择适当的令牌身份验证机制来保护 Quarkus 应用程序。
身份验证机制用例列表
-
quarkus-oidc需要 OpenID Connect 供应商,如 Keycloak,它可以验证 bearer 令牌或使用授权代码流验证最终用户。在这两种情况下,quarkus-oidc需要连接到指定的 OpenID Connect 供应商。 -
如果用户身份验证需要授权代码流,或者您需要支持多个租户,请使用
quarkus-oidc。quarkus-oidc还可以使用授权代码流和 Bearer 访问令牌来请求用户信息。 -
如果必须验证 bearer 令牌,请使用
quarkus-oidc或quarkus-smallrye-jwt。 -
如果您的 bearer 令牌采用 JSON Web 令牌(JWT)格式,您可以使用上述列表中的任何扩展。
quarkus-oidc和quarkus-smallrye-jwt支持刷新 OpenID Connect 提供程序轮转密钥时设置的JsonWebKey(JWK)。因此,如果必须避免远程令牌内省,或者提供程序不支持的远程令牌,请使用quarkus-oidc或quarkus-smallrye-jwt来验证 JWT 令牌。 -
要远程内省 JWT 令牌,您可以使用
quarkus-oidc使用远程内省来验证不透明或二进制令牌。quarkus-smallrye-jwt不支持对不透明或 JWT 令牌的远程内省,而是依赖于通常从 OpenID Connect 提供程序检索的本地可用密钥。 -
quarkus-oidc和quarkus-smallrye-jwt支持 JWT 和不透明令牌注入端点代码中。注入的 JWT 令牌提供有关用户的更多信息。所有扩展都可以将令牌注入为Principal。 -
Quarkus-smallrye-jwt支持比quarkus-oidc更多的密钥格式。quarkus-oidc只使用属于 JWK 设置的 JWK 格式的密钥,而quarkus-smallrye-jwt支持 PEM 密钥。 -
quarkus-smallrye-jwt处理本地签名、内部签名和加密令牌。相反,虽然quarkus-oidc也可以验证这些令牌,但它将其视为不透明令牌,并通过远程内省对其进行验证。
架构注意事项有助于您决定使用不透明或 JSON Web 令牌(JWT)令牌格式。不透明令牌往往比 JWT 令牌要短,但需要在提供商数据库中维护大多数令牌关联状态。不透明令牌是有效的数据库指针。
JWT 令牌比不透明令牌要长。然而,提供商通过将大多数令牌关联状态存储为令牌声明,并对其进行签名或加密来有效地将大多数令牌关联状态委派给客户端。
| 功能需要 | 身份验证机制 | |
|---|---|---|
|
|
| |
| bearer JWT 验证 | 本地验证或内省 | 本地验证 |
| bearer 不透明令牌验证 | 内省 | 否 |
|
刷新 | 是 | 是 |
|
将令牌表示为 | 是 | 是 |
| 将 JWT 注入 MP JWT | 是 | 是 |
| 授权代码流 | 是 | 否 |
| 多租户 | 是 | 否 |
| 用户信息支持 | 是 | 否 |
| PEM 密钥格式支持 | 否 | 是 |
| secretKey 支持 | 否 | JSON Web 密钥(JWK)格式 |
| 内部签名和加密或加密令牌 | 内省 | 本地验证 |
| 自定义令牌验证 | 否 | 使用注入的 JWT 解析器 |
| JWT 作为 Cookie 支持 | 否 | 是 |
2.5. 组合身份验证机制 复制链接链接已复制到粘贴板!
如果不同的源提供用户凭证,您可以组合身份验证机制。例如,您可以组合内置的 Basic 和 Quarkus quarkus-oidc Bearer 令牌身份验证机制。
当第一个 SecurityIdentity 由其中一个身份验证机制生成后,身份验证过程就会马上完成。
2.5.1. 包含的身份验证 复制链接链接已复制到粘贴板!
在某些情况下,可能要求所有注册的身份验证机制都创建其 SecurityIdentity。当用户通过虚拟专用网络进行身份验证时,或者当前令牌必须绑定到令牌验证才能成功通过 Mutual TLS 身份验证时,可能需要使用令牌验证。
在 Quarkus 中,此类身份验证名为 inclusive,您可以启用它,如下所示:
quarkus.http.auth.inclusive=true
quarkus.http.auth.inclusive=true
如果身份验证包含,则由第一个身份验证机制创建的 SecurityIdentity 可以注入到应用程序代码中。例如,如果需要 Mutual TLS 身份验证和 基本身份验证机制身份验证,则 Mutual TLS 身份验证机制 将首先创建 SecurityIdentity。
Mutual TLS 身份验证机制在启用包含身份验证时具有最高的优先级,以确保注入的 SecurityIdentity 始终代表 双向 TLS 身份验证,并可用于获取由其他身份验证机制提供的 SecurityIdentity 身份的访问。
可以在第一个 SecurityIdentity 上作为 quarkus.security.identities 属性访问额外的 SecurityIdentity 实例,但访问这些额外的身份可能并不需要访问这些额外身份,例如,当 Mutual TLS 身份验证和 OIDC Bearer 身份验证机制都已合并并完成其身份验证时,经过身份验证的 bearer 令牌可以注入令牌凭证,以及 Mutual TLS 身份验证 创建的 SecurityIdentity。下面是一个示例:
您不能组合 Quarkus quarkus-oidc Bearer 令牌和 smallrye-jwt 身份验证机制,因为这两种机制试图验证从 HTTP Bearer 令牌身份验证方案中提取的令牌。
2.5.2. 基于路径的身份验证 复制链接链接已复制到粘贴板!
2.5.2.1. 使用 HTTP 安全策略启用基于路径的身份验证 复制链接链接已复制到粘贴板!
以下配置示例演示了如何为给定请求路径强制执行单个可选择的身份验证机制:
确保 auth-mechanism 属性的值与 HttpAuthenticationMechanism 支持的身份验证方案匹配,例如 基本的、bearer 或 表单。
2.5.2.2. 使用注解为 Jakarta REST 端点启用基于路径的身份验证 复制链接链接已复制到粘贴板!
可以使用注解来选择特定于每个 Jakarta REST 端点的身份验证机制。只有在禁用 主动 身份验证时,此功能才会启用。因此,注解只能在与 REST 端点匹配后选择验证机制。以下是如何为每个 REST 端点选择身份验证机制:
quarkus.http.auth.proactive=false
quarkus.http.auth.proactive=false
| 身份验证机制^ | 注解 |
|---|---|
| 基本身份验证机制 |
|
| 基于表单的验证机制 |
|
| 双向 TLS 身份验证机制 |
|
| bearer 令牌身份验证机制 |
|
| OIDC 授权代码流机制 |
|
| smallrye JWT 身份验证机制 |
|
Quarkus 会自动保护使用身份验证机制注解注解的端点。当 REST 端点和资源中没有标准安全注解时,会为您添加 io.quarkus.security.Authenticated 注解。
也可以使用 io.quarkus.vertx.http.runtime.security.annotation.HttpAuthenticationMechanism 注释来选择基于其方案的任何身份验证机制。基于注释的 analogy 到 quarkus.http.auth.permission.basic.auth-mechanism=custom 配置属性是 @HttpAuthenticationMechanism ("custom") 注释。
为了与各种 Jakarta EE 规格保持一致,建议始终重复注释,而不依赖于注解继承。
2.5.2.3. 使用包含的验证启用基于路径的身份验证 复制链接链接已复制到粘贴板!
默认情况下,Quarkus 只支持 每个路径的一个验证机制的基于路径的 验证。如果需要将多个身份验证机制用于基于路径的身份验证,您可以编写一个自定义 HttpAuthenticationMechanism 部分,如 Security Tips and Tricks 指南中有多个 HttpAuthenticationMechanism 部分所述。另一种选择是在 lax 模式中启用 Inclusive 身份验证,并编写自定义 HttpSecurityPolicy 或 PermissionChecker,验证所有注册的 HTTP 身份验证机制是否创建了其机制特定的 SecurityIdentity。
在 lax 模式中启用包含的身份验证
quarkus.http.auth.inclusive-mode=lax quarkus.http.auth.inclusive=true
quarkus.http.auth.inclusive-mode=lax
quarkus.http.auth.inclusive=true
- 1
- 默认情况下,包含的身份验证要求所有注册的 HTTP 身份验证机制都必须创建
SecurityIdentity。但是,在 lax 模式中,如果至少一个注册的HttpAuthenticationMechanism创建了SecurityIdentity,则身份验证会成功。
假设我们有 3 个注册机制 mTLS、Basic 和 OIDC,您只需要 Basic 和 mTLS 身份验证才能成功访问 hello 方法。在这种情况下,在 lax 模式中启用包含的身份验证,可以检查生成身份的机制,如下例所示:
HTTP 身份验证机制检查示例
- 1
- 只有在确认
mTLS和基本身份验证机制都已验证当前请求时,才允许访问端点。
2.5.2.4. 如何将其与 HTTP 安全策略合并 复制链接链接已复制到粘贴板!
定义允许访问单个资源的角色的最简单方法是 @RolesAllowed 注释。但是,也可以使用 HTTP 安全策略,如下例所示:
quarkus.http.auth.policy.roles1.roles-allowed=user quarkus.http.auth.permission.roles1.paths=/hello/code-flow quarkus.http.auth.permission.roles1.applies-to=JAXRS quarkus.http.auth.permission.roles1.policy=roles1 quarkus.http.auth.permission.roles1.methods=GET
quarkus.http.auth.policy.roles1.roles-allowed=user
quarkus.http.auth.permission.roles1.paths=/hello/code-flow
quarkus.http.auth.permission.roles1.applies-to=JAXRS
quarkus.http.auth.permission.roles1.policy=roles1
quarkus.http.auth.permission.roles1.methods=GET
2.6. 主动验证 复制链接链接已复制到粘贴板!
主动验证在 Quarkus 中默认启用。这意味着,如果传入请求具有凭证,则请求将始终通过身份验证,即使目标页面不需要身份验证。如需更多信息,请参阅 Quarkus 主动身份验证 指南。
2.7. 参考 复制链接链接已复制到粘贴板!
第 3 章 用户身份供应商 复制链接链接已复制到粘贴板!
在 Quarkus 安全框架中,身份提供程序通过验证用户身份在身份验证和授权中扮演重要角色。IdentityProvider 创建一个 SecurityIdentity 实例,它会在用户身份验证过程中用来验证和授权对 Quarkus 应用的访问请求。
IdentityProvider 将 HttpAuthenticationMechanism 提供的身份验证凭据转换为 SecurityIdentity 实例。
有些扩展,如 OIDC 和 SmallRye JWT 的扩展,包括特定于支持的身份验证流的内联 IdentityProvider 实现。例如,quarkus-oidc 使用自己的 IdentityProvider 将令牌转换为 SecurityIdentity 实例。
如果使用基于 Basic 或 form 的身份验证,您必须添加一个 IdentityProvider 实例,将用户名和密码转换为 SecurityIdentity 实例。
要开始使用 Quarkus 中的安全性,请考虑将 Quarkus 内置基本 HTTP 身份验证与 Jakarta Persistence 身份提供程序相结合,以启用基于角色的访问控制(RBAC)。
有关基本身份验证、其机制和相关身份提供程序的更多信息,请参阅以下资源:
第 4 章 主动验证 复制链接链接已复制到粘贴板!
了解如何在 Quarkus 中管理主动身份验证,包括自定义设置和处理异常。获取各种应用程序场景的实用见解和策略。
主动验证在 Quarkus 中默认启用。它确保所有传入的请求都通过身份验证,即使目标页面不需要身份验证。因此,带有无效凭证的请求将被拒绝,即使目标页面是公共的。没有凭证的请求不会被拒绝,因为允许匿名请求。
只有在目标页面需要时才需要身份验证时,可以关闭此默认行为。要关闭主动身份验证,以便仅在目标页面需要时才进行身份验证,请按如下所示修改 application.properties 配置文件:
quarkus.http.auth.proactive=false
quarkus.http.auth.proactive=false
如果您关闭主动身份验证,身份验证过程仅在请求身份时运行。可以请求一个身份,因为需要需要用户进行身份验证的安全规则,或者因为需要对当前身份进行编程访问。
如果没有使用主动身份验证,访问 SecurityIdentity 是一个阻止操作。这是因为身份验证可能已经发生,访问 SecurityIdentity 可能需要调用外部系统,如数据库,这可能会阻止操作。对于阻止应用程序,这并不是一个问题。但是,如果您在被动应用程序中禁用了身份验证,则会失败,因为您无法阻止 I/O 线程的操作。要临时解决这个问题,您需要 @Inject 一个 io.quarkus.security.identity.CurrentIdentityAssociation 实例,并调用 Uni<SecurityIdentity> getDeferredIdentity (); 方法。然后,您可以订阅生成的 Uni,以便在身份验证完成后获得通知,且身份可用。
您仍然可以从使用 @RolesAllowed 、@Authenticated、如果路由响应是同步,则也对 Reactive 路由 也有效。
@Authenticated ,或具有相应配置授权检查的端点同时访问 Quarkus REST 中的 SecurityIdentity getIdentity () (以前为 RESTEasy Reactive)。
禁用主动身份验证后,如果未同步返回值的安全方法,则 CDI Bean 上使用 的标准安全注解 在 I/O 线程上无法正常工作。由于需要这些方法访问 SecurityIdentity,就会产生这个限制。
以下示例定义了 HelloResource 和 HelloService。任何对 /hello 的 GET 请求都在 I/O 线程上运行,并抛出 BlockingOperationNotAllowedException 异常。
修复示例的方法不止一种:
-
通过注解带有
@Blocking的hello端点来切换到 worker 线程。 -
使用被动或异步数据类型更改
sayHello方法返回类型。 -
将
@RolesAllowed注释移到端点。这可能是安全的方法之一,因为从端点方法访问SecurityIdentity并不是阻塞操作。
4.1. 激活 CDI 请求上下文 复制链接链接已复制到粘贴板!
您可能需要在身份验证和授权期间注入 @RequestScoped Bean。这是在 SecurityIdentity 增强过程中访问数据库的一个很好的例子,这在" 安全提示和 Tricks"指南的"安全身份自定义 "部分中描述。如果身份验证或授权失败并显示 jakarta.enterprise.context.ContextNotActiveException,则禁用主动身份验证通常是最佳解决方案。用户也可以使用 @ActivateRequestContext 注释激活 CDI 请求上下文。但是,一些 CDI Bean 可能未就绪。
此解决方案的一个例外是应用端点 使用配置 进行授权保护时的情况。有关更多信息,请参阅"Authorization of Web 端点"指南中的 Inject RequestScoped Bean into HttpSecurityPolicy 部分以了解更多信息。
4.2. 自定义身份验证异常响应 复制链接链接已复制到粘贴板!
您可以使用 Jakarta REST ExceptionMapper 来捕获 Quarkus 安全身份验证异常,如 io.quarkus.security.AuthenticationFailedException。例如:
有些 HTTP 身份验证机制必须处理身份验证异常本身,才能创建正确的身份验证问题。例如: io.quarkus.oidc.runtime.CodeAuthenticationMechanism,它管理 OpenID Connect (OIDC)授权代码流身份验证,必须构建正确的重定向 URL 并设置状态 Cookie。因此,避免使用自定义异常映射器自定义由此类机制引发的身份验证异常。相反,一种更安全的方法是确保启用主动身份验证并使用 Vert.x HTTP 路由失败处理程序。这是因为事件发送到带有正确响应状态和标头的处理程序。然后,您必须只自定义响应,例如: