搜索

2.2. 内置身份验证机制

download PDF

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();
}

以下属性可用于配置基于表单的身份验证:

lock 在构建时修复的配置属性 - 所有其他配置属性在运行时可覆盖

配置属性

类型

default

quarkus.http.auth.permission."permissions".enabled

确定是否启用整个权限集。默认情况下,如果定义了权限集,则会启用它。

环境变量: QUARKUS_HTTP_AUTH_PERMISSION__PERMISSIONS__ENABLED

布尔值

 

quarkus.http.auth.permission."permissions".policy

此权限集链接到的 HTTP 策略。有三个内置策略:allow、deny 和 authenticated。可以定义基于角色的策略,扩展可以添加自己的策略。

环境变量: QUARKUS_HTTP_AUTH_PERMISSION__PERMISSIONS__POLICY

string

必需 exclamation circle

quarkus.http.auth.permission."permissions".methods

此权限集的方法应用到。如果没有设置,则适用于所有方法。请注意,如果请求与任何权限集中的任何路径匹配,但由于未列出方法,则请求将被拒绝。方法特定权限优先于未设置任何方法的匹配项。这意味着,如果 Quarkus 配置为允许 GET 和 POST 请求到 /admin,且没有将其他权限配置为 /admin 将被拒绝。

环境变量: QUARKUS_HTTP_AUTH_PERMISSION__PERMISSIONS__METHODS

字符串列表

 

quarkus.http.auth.permission."permissions".paths

此权限检查应用到的路径。如果路径以 86] 结尾,则这被视为路径前缀,否则它将被视为完全匹配。匹配会以长度为基础完成,因此最具体的路径匹配具有优先权。如果多个权限集与同一路径匹配,那么显式方法匹配优先于设置方法,否则应用最严格的权限。

环境变量: QUARKUS_HTTP_AUTH_PERMISSION__PERMISSIONS__PATHS

字符串列表

 

quarkus.http.auth.permission."permissions".auth-mechanism

必须用来验证用户身份的路径特定身份验证机制。它需要匹配 HttpCredentialTransport 身份验证方案,如 'basic'、'bearer'、'form' 等。

环境变量: QUARKUS_HTTP_AUTH_PERMISSION__PERMISSIONS__AUTH_MECHANISM

string

 

quarkus.http.auth.permission."permissions".shared

表示除了具有获奖路径的策略外,此策略还始终适用于匹配的路径。避免创建多个共享策略,以最大程度降低性能影响。

环境变量: QUARKUS_HTTP_AUTH_PERMISSION__PERMISSIONS__SHARED

布尔值

false

quarkus.http.auth.permission."permissions".applies-to

权限检查是否应该应用到所有匹配路径,还是专用于 Jakarta REST 资源的路径。

环境变量: QUARKUS_HTTP_AUTH_PERMISSION__PERMISSIONS__APPLIES_TO

All :适用于所有匹配路径。

jaxrs: Declares,权限检查必须仅应用于 Jakarta REST 请求路径。使用这个选项,延迟权限检查是否使用匹配的 Jakarta REST 端点上的注解选择验证机制。如果使用以下 REST 端点注解,则必须设置这个选项:- io.quarkus.oidc.Tenant 注解,它选择带有租户标识符的 OIDC 身份验证机制 - io.quarkus.vertx.http.runtime.security.annotation.BasicAuthentication,它选择 Basic 身份验证机制 - io.quarkus.vertx.http.runtime.security.annotation.FormAuthentication 选择基于 Form 的身份验证机制 - io.quarkus.vertx.http.runtime.security.annotation.MTLS Authentication,它选择 mTLS 身份验证机制 - io.quarkus.security.webauthn.WebAuth n 选择 WebAuth 身份验证机制 - io.quarkus.oidc.BearerToken Authentication,它选择 OpenID Connect Bearer 令牌身份验证机制 - - io.quarkus.oidc.Authorization CodeFlow,它选择 OpenID Connect Code 身份验证机制

all

quarkus.http.auth.policy."role-policy".roles-allowed

允许访问此策略保护的资源的角色。默认情况下,任何经过身份验证的用户都允许访问。

环境变量: QUARKUS_HTTP_AUTH_POLICY_ROLE_POLICY__ROLES_ALLOWED

字符串列表

**

quarkus.http.auth.policy."role-policy".roles."role-name"

根据 SecurityIdentity 已存在的角色,为 SecurityIdentity 添加授予的角色。例如,Quarkus OIDC 扩展可以映射来自验证的 JWT 访问令牌的角色,您可能希望将它们重新映射到部署特定的角色。

环境变量: QUARKUS_HTTP_AUTH_POLICY__ROLE_POLICY__ROLES__ROLE_NAME_

Map<String,List<String>>

 

quarkus.http.auth.policy."role-policy".permissions."role-name"

如果成功应用此策略,则授予 SecurityIdentity 的权限(策略允许请求继续),并且经过身份验证的请求具有必要的角色。例如,您可以通过设置 quarkus.http.auth.policy.role-policy1.permissions. admin =perm1:action1,perm1: action2 配置属性 将每个m1 的权限映射为 role admin授予的权限用于通过 @PermissionsAllowed 注释进行授权。

环境变量: QUARKUS_HTTP_AUTH_POLICY__ROLE_POLICY__PERMISSIONS__ROLE_NAME_

Map<String,List<String>>

 

quarkus.http.auth.policy."role-policy".permission-class

此策略授予的权限将通过此配置属性指定的 java.security.Permission 实施来创建。权限类必须声明一个接受权限名称(String )或权限名称和操作(字符串、字符串[])的构造器。如果您以原生模式运行应用程序,则必须注册权限类,以反映其是否运行您的应用程序。

环境变量: QUARKUS_HTTP_AUTH_POLICY__ROLE_POLICY__PERMISSION_CLASS

string

io.quarkus.security.StringPermission

quarkus.http.auth.roles-mapping."role-name"

SecurityIdentity 角色映射到部署特定的角色,并将匹配的角色添加到 SecurityIdentity

例如,如果 SecurityIdentity 具有用户角色,并且端点使用 'UserRole' 角色进行保护,则使用此属性将用户角色映射到 UserRole 角色,并且具有 SecurityIdentity 角色,并且具有 user UserRole 角色。

环境变量: QUARKUS_HTTP_AUTH_ROLES_MAPPING__ROLE_NAME_

Map<String,List<String>>

 

quarkus.http.auth.certificate-role-attribute

客户端证书属性,其值将根据证书属性文件中指定的角色映射映射到"安全Identity"角色。属性必须是 Relative Distinguished Names (RDN)或 Subject Alternative Names (SAN)之一。默认情况下,通用名称(CN)属性值用于角色映射。支持的值有:

  • rdn type - Distinguished Name 字段。例如 'CN' 代表 Common Name 字段。目前不支持 Multivalued RNDs 和相同属性的多个实例。
  • 'SAN_RFC822' - Subject Alternative Name field RFC 822 Name.
  • 'SAN_URI' - Subject Alternative Name field Uniform Resource Identifier (URI)。
  • 'SAN_ANY' - Subject Alternative Name field Other Name.请注意,只支持 UTF8 标识符映射的简单情况。例如,您可以将 'other-identifier' 映射到 SecurityIdentity 角色。如果您使用 'openssl' 工具,则支持其他名称定义类似如下: subjectAltName=otherName:1.2.3.4;UTF8:other-identifier

环境变量: QUARKUS_HTTP_AUTH_CERTIFICATE_ROLE_ATTRIBUTE

string

CN

quarkus.http.auth.certificate-role-properties

包含客户端证书属性值到角色映射的属性文件。只有在使用 quarkus.http.ssl.client-auth=requiredquarkus.http.ssl.client-auth=request 启用 mTLS 身份验证机制时,才使用它。

属性文件预期具有 CN_VALUE=role1,role,…​,roleN 格式,并使用 UTF-8 进行编码。

环境变量: QUARKUS_HTTP_AUTH_CERTIFICATE_ROLE_PROPERTIES

path

 

quarkus.http.auth.realm

身份验证域

环境变量: QUARKUS_HTTP_AUTH_REALM

string

 

quarkus.http.auth.form.login-page

登录页面。可以通过设置 quarkus.http.auth.form.login-page= 来禁用重定向到登录页面。

环境变量: QUARKUS_HTTP_AUTH_FORM_LOGIN_PAGE

string

/login.html

quarkus.http.auth.form.username-parameter

用户名字段名称。

环境变量: QUARKUS_HTTP_AUTH_FORM_USERNAME_PARAMETER

string

j_username

quarkus.http.auth.form.password-parameter

密码字段名称。

环境变量: QUARKUS_HTTP_AUTH_FORM_PASSWORD_PARAMETER

string

j_password

quarkus.http.auth.form.error-page

错误页面。可以通过设置 quarkus.http.auth.form.error-page= 来禁用重定向到错误页面。

环境变量: QUARKUS_HTTP_AUTH_FORM_ERROR_PAGE

string

/error.html

quarkus.http.auth.form.landing-page

如果没有保存的页面要重定向到,则要重定向到的登录页面。可以通过设置 quarkus.http.auth.form.landing-page= 来禁用到登录页面。

环境变量: QUARKUS_HTTP_AUTH_FORM_LANDING_PAGE

string

/index.html

quarkus.http.auth.form.location-cookie

选项控制用于将用户重新定向到他们要访问的位置的 Cookie 名称。

环境变量: QUARKUS_HTTP_AUTH_FORM_LOCATION_COOKIE

string

quarkus-redirect-location

quarkus.http.auth.form.timeout

当达到不活跃超时时,不活动(空闲)超时,不会续订 Cookie,并强制使用新的登录。

环境变量: QUARKUS_HTTP_AUTH_FORM_TIMEOUT

duration question circle

PT30M

quarkus.http.auth.form.new-cookie-interval

Cookie 在新的 Cookie 被更新超时替代之前如何获得,也称为"renewal-timeout"。请注意,较小的值会导致服务器负载稍多(因为新加密的 Cookie 将更频繁生成);但是,较大的值会影响不活动超时,因为在生成 Cookie 时设置了超时。例如,如果这设为 10 分钟,并且不活跃超时为 30m,如果用户的最后一个请求为 9m,则实际超时将在最后一次请求后发生 21m,因为仅在生成新 Cookie 时超时才会刷新。也就是说,在服务器端不会跟踪超时;时间戳采用 Cookie 本身进行编码和加密,并通过每个请求进行解密和解析。

环境变量: QUARKUS_HTTP_AUTH_FORM_NEW_COOKIE_INTERVAL

duration question circle

PT1M

quarkus.http.auth.form.cookie-name

用于存储持久会话的 Cookie

环境变量: QUARKUS_HTTP_AUTH_FORM_COOKIE_NAME

string

quarkus-credential

quarkus.http.auth.form.cookie-path

会话和位置 Cookie 的 Cookie 路径。

环境变量: QUARKUS_HTTP_AUTH_FORM_COOKIE_PATH

string

/

quarkus.http.auth.form.http-only-cookie

设置 HttpOnly 属性,以防止通过 JavaScript 访问 Cookie。

环境变量: QUARKUS_HTTP_AUTH_FORM_HTTP_ONLY_COOKIE

布尔值

false

quarkus.http.auth.form.cookie-same-site

会话和位置 Cookie 的 SameSite 属性。

环境变量: QUARKUS_HTTP_AUTH_FORM_COOKIE_SAME_SITE

strict,lax,none

strict

关于 Duration 格式

要写入持续时间值,请使用标准 java.time.Duration 格式。如需更多信息,请参阅 Duration#parse ()Java API 文档

您还可以使用简化的格式,从数字开始:

  • 如果值只是一个数字,它代表时间(以秒为单位)。
  • 如果值为数字,后跟 ms,代表时间(毫秒)。

在其他情况下,简化的格式被转换为 java.time.Duration 格式以进行解析:

  • 如果该值是一个数字,后跟 hms,则前缀为 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
1
服务器私钥所在的密钥存储。
2
从中加载可信证书的信任存储。
3
quarkus.http.ssl.client-auth 设置为 required 使服务器需要客户端证书。如果服务器应该接受没有证书的请求,您可以将它设置为 REQUEST。当支持多个身份验证方法时,此设置很有用。
4
定义一个策略,其中只有经过身份验证的用户可以访问应用程序中的资源。
5
禁用普通 HTTP 协议,要求所有请求使用 HTTPS。当您将 quarkus.http.ssl.client-auth 设置为 required 时,quarkus.http.insecure-requests 会自动禁用。

当传入请求与信任存储中的有效证书匹配时,您的应用程序可以通过注入 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
1
cert-role-mappings.properties classpath 资源包含证书的 CN 值映射,格式为 CN=roleCN=role1,role2 等。让我们假设它包含三个条目: alice=user、admin、 bob=userjdoe=tester
2 3 4
使用 HTTP 安全策略要求 SecurityIdentity 必须具有 useradmin 角色,才能被授权请求。

根据前面的配置,如果客户端证书的 CN 属性等于 alicebob,如果请求等同于 jdoe,则请求被授权。

2.2.3.2. 使用证书属性来增强 SecurityIdentity

如果 角色选项的自动映射证书属性不适用,则始终可以注册 SecurityIdentityAugmentor。自定义 SecurityIdentityAugmentor 可以检查不同的客户端证书属性的值,并相应地增强 SecurityIdentity

有关自定义安全身份的更多信息,请参阅 Quarkus " 安全提示 和 tricks" 指南中的 安全身份自定义 部分。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.