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
类似如下:
quarkus.http.auth.form.enabled=true quarkus.http.auth.form.login-page=login.html quarkus.http.auth.form.landing-page=hello quarkus.http.auth.form.error-page= # Define testing user quarkus.security.users.embedded.enabled=true quarkus.security.users.embedded.plain-text=true quarkus.security.users.embedded.users.alice=alice quarkus.security.users.embedded.roles.alice=user
在 application.properties 文件中配置用户名、secret 和角色只适用于测试场景。对于保护生产应用,使用数据库或 LDAP 存储此信息至关重要。如需更多信息,您可以查看 带有 Jakarta Persistence 的 Quarkus 安全性,或其他 启用基本身份验证 中所述。
应用程序登录页面将包含类似如下的 HTML 表单:
<form action="/j_security_check" method="post"> <label>Username</label> <input type="text" placeholder="Username" name="j_username" required> <label>Password</label> <input type="password" placeholder="Password" name="j_password" required> <button type="submit">Login</button> </form>
使用单页应用程序(SPA),您通常希望通过删除默认页面路径来避免重定向,如下例所示:
# do not redirect, respond with HTTP 200 OK quarkus.http.auth.form.landing-page= # do not redirect, respond with HTTP 401 Unauthorized quarkus.http.auth.form.login-page= quarkus.http.auth.form.error-page= # HttpOnly must be false if you want to log out on the client; it can be true if logging out from the server quarkus.http.auth.form.http-only-cookie=false
现在,您已为 SPA 禁用了重定向,您必须以编程方式从客户端登录并注销。以下是登录 j_security_check
端点的 JavaScript 方法示例,并通过销毁 Cookie 来注销应用。
const login = () => { // Create an object to represent the form data const formData = new URLSearchParams(); formData.append("j_username", username); formData.append("j_password", password); // Make an HTTP POST request using fetch against j_security_check endpoint fetch("j_security_check", { method: "POST", body: formData, headers: { "Content-Type": "application/x-www-form-urlencoded", }, }) .then((response) => { if (response.status === 200) { // Authentication was successful console.log("Authentication successful"); } else { // Authentication failed console.error("Invalid credentials"); } }) .catch((error) => { console.error(error); }); };
要从客户端注销 SPA,cookie 必须设为 quarkus.http.auth.form.http-only-cookie=false
,以便您可以销毁 Cookie,并可能重定向到您的主页。
const logout= () => { // delete the credential cookie, essentially killing the session const removeCookie = `quarkus-credential=; Max-Age=0;path=/`; document.cookie = removeCookie; // perform post-logout actions here, such as redirecting back to your login page };
要从服务器注销 SPA,cookie 可以设置为 quarkus.http.auth.form.http-only-cookie=true
,并使用此示例代码销毁 Cookie。
@ConfigProperty(name = "quarkus.http.auth.form.cookie-name") String cookieName; @Inject CurrentIdentityAssociation identity; @POST public Response logout() { if (identity.getIdentity().isAnonymous()) { throw new UnauthorizedException("Not authenticated"); } final NewCookie removeCookie = new NewCookie.Builder(cookieName) .maxAge(0) .expiry(Date.from(Instant.EPOCH)) .path("/") .build(); return Response.noContent().cookie(removeCookie).build(); }
以下属性可用于配置基于表单的身份验证:
在构建时修复的配置属性 - 所有其他配置属性在运行时可覆盖
配置属性 | 类型 | default |
确定是否启用整个权限集。默认情况下,如果定义了权限集,则会启用它。
环境变量: | 布尔值 | |
此权限集链接到的 HTTP 策略。有三个内置策略:allow、deny 和 authenticated。可以定义基于角色的策略,扩展可以添加自己的策略。
环境变量: | string | 必需 |
此权限集的方法应用到。如果没有设置,则适用于所有方法。请注意,如果请求与任何权限集中的任何路径匹配,但由于未列出方法,则请求将被拒绝。方法特定权限优先于未设置任何方法的匹配项。这意味着,如果 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 |
|
设置 HttpOnly 属性,以防止通过 JavaScript 访问 Cookie。
环境变量: | 布尔值 |
|
会话和位置 Cookie 的 SameSite 属性。
环境变量: |
|
|
要写入持续时间值,请使用标准 java.time.Duration
格式。如需更多信息,请参阅 Duration#parse ()Java API 文档。
您还可以使用简化的格式,从数字开始:
- 如果值只是一个数字,它代表时间(以秒为单位)。
-
如果值为数字,后跟
ms
,代表时间(毫秒)。
在其他情况下,简化的格式被转换为 java.time.Duration
格式以进行解析:
-
如果该值是一个数字,后跟
h
、m
或s
,则前缀为PT
。 -
如果值为数字,后跟
d
,则会以P
为前缀。
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
JKS 变得不常使用。从 Java 9 开始,Java 的默认密钥存储格式是 PKCS12。JKS 和 PKCS12 之间的显著区别在于 JKS 是特定于 Java 的格式。相反,PKCS12 是一种标准化、不中立的方式,用于存储加密的私钥和证书。
以下是启用 mTLS 的示例配置:
quarkus.http.ssl.certificate.key-store-file=server-keystore.jks 1 quarkus.http.ssl.certificate.key-store-password=the_key_store_secret quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks 2 quarkus.http.ssl.certificate.trust-store-password=the_trust_store_secret quarkus.http.ssl.client-auth=required 3 quarkus.http.auth.permission.default.paths=/* 4 quarkus.http.auth.permission.default.policy=authenticated quarkus.http.insecure-requests=disabled 5
当传入请求与信任存储中的有效证书匹配时,您的应用程序可以通过注入 SecurityIdentity
获取主题,如下所示:
获取主题
@Inject SecurityIdentity identity; @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return String.format("Hello, %s", identity.getPrincipal().getName()); }
您还可以使用以下示例中介绍的代码获取证书:
获取证书
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 身份验证,如下所示:
quarkus.http.ssl.certificate.key-store-file=server-keystore.jks quarkus.http.ssl.certificate.key-store-password=the_key_store_secret quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks quarkus.http.ssl.certificate.trust-store-password=the_trust_store_secret quarkus.http.ssl.client-auth=required quarkus.http.insecure-requests=disabled quarkus.http.auth.certificate-role-properties=cert-role-mappings.properties 1 quarkus.http.auth.permission.certauthenticated.paths=/* 2 quarkus.http.auth.permission.certauthenticated.policy=role-policy-cert 3 quarkus.http.auth.policy.role-policy-cert.roles-allowed=user,admin 4
根据前面的配置,如果客户端证书的 CN 属性等于 alice
或 bob
,如果请求等同于 jdoe
,则请求被授权。
2.2.3.2. 使用证书属性来增强 SecurityIdentity
如果 角色选项的自动映射证书属性不适用,则始终可以注册 SecurityIdentityAugmentor
。自定义 SecurityIdentityAugmentor
可以检查不同的客户端证书属性的值,并相应地增强 SecurityIdentity
。
有关自定义安全身份的更多信息,请参阅 Quarkus " 安全提示 和 tricks" 指南中的 安全身份自定义 部分。