安全入门


Red Hat build of Quarkus 3.8

Red Hat Customer Content Services

摘要

本指南演示了如何使用基本身份验证和 Jakarta Persistence 保护 Quarkus 应用程序,指导您完成先决条件、应用程序设置和测试。它涵盖了创建 Maven 项目、验证依赖项、编写应用程序端点、定义用户实体和配置基本身份验证。它包括使用 PostgreSQL 的 Dev Services 来测试应用,使用 curl 或浏览器编译、运行和验证应用安全性。最终,您将了解如何实施基于角色的访问控制,准备好进行更高级的机制,如 OIDC。它详细介绍了使用 Jakarta Persistence 进行安全性,包括实体规格、角色存储和密码散列。

提供有关红帽构建的 Quarkus 文档的反馈

要报告错误或改进文档,请登录到 Red Hat JIRA 帐户并提交问题。如果您没有 Red Hat Jira 帐户,则会提示您创建一个帐户。

步骤

  1. 单击以下链接 以创建 ticket
  2. Summary 中输入问题的简短描述。
  3. Description 中提供问题或功能增强的详细描述。包括一个指向文档中问题的 URL。
  4. Submit 创建问题,并将问题路由到适当的文档团队。

使开源包含更多

红帽致力于替换我们的代码、文档和 Web 属性中有问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。详情请查看 CTO Chris Wright 的信息

使用内置 Quarkus 基本身份验证 和 Jakarta Persistence 身份提供程序保护 Quarkus 应用程序端点,启用基于角色的访问控制。

Jakarta Persistence IdentityProvider 验证并将 基本身份验证 用户名和密码对转换为 SecurityIdentity 实例,该实例用于授权访问请求,从而使 Quarkus 应用程序安全。

有关 Jakarta Persistence 的更多信息,请参阅使用 Jakarta Persistence 的 Quarkus 安全性指南。

本教程准备了在 Quarkus 中实施更高级的安全机制,例如如何使用 OpenID Connect (OIDC)身份验证机制。

1.1. 先决条件

要完成本指南,您需要:

  • 大约 15 分钟
  • IDE
  • 正确配置了 JAVA_HOME 的 JDK 17+
  • Apache Maven 3.9.6
  • 如果要使用 Quarkus CLI
  • 如果要构建原生可执行文件(如果使用 原生容器 构建,则为 Docker)正确安装和配置 Mandrel 或 GraalVM

1.2. 构建应用程序

本教程提供了创建带有端点以说明各种授权策略的详细步骤:

Expand
端点描述

/api/public

此端点可以在不进行身份验证的情况下访问,允许匿名访问。

/api/admin

使用基于角色的访问控制(RBAC)进行保护,此端点只能被具有 admin 角色的用户访问。使用 @RolesAllowed 注释,以声明性方式控制访问。

/api/users/me

另外,通过 RBAC 保护,此端点只能被具有 user 角色的用户访问。它将调用者的用户名返回为字符串。

提示

要检查完成的示例,请下载 存档或 克隆 Git 存储库:

git clone https://github.com/quarkusio/quarkus-quickstarts.git -b 3.8
Copy to Clipboard Toggle word wrap

您可以在 security-jpa-quickstart 目录中找到 解决方案。

1.3. 创建和验证 Maven 项目

要使 Quarkus Security 能够将安全源映射到 Jakarta Persistence 实体,请确保本教程中的 Maven 项目包含 quarkus-security-jpa 扩展。

注意

带有 Panache 的 Hibernate ORM 用于存储您的用户身份,但您也可以使用带有 quarkus-security-jpa 扩展的 Hibernate ORM

您还必须添加您首选的数据库连接器库。本例中的说明将 PostgreSQL 数据库用于身份存储。

1.3.1. 创建 Maven 项目

您可以使用 Security Jakarta Persistence 扩展创建新的 Maven 项目,或将扩展添加到现有 Maven 项目中。您可以使用 Hibernate ORM 或 Hibernate Reactive。

  • 要使用 Jakarta Persistence 扩展创建新的 Maven 项目,请完成以下步骤之一:

    • 要使用 Hibernate ORM 创建 Maven 项目,请使用以下命令:
  • 使用 Quarkus CLI:

    quarkus create app org.acme:security-jpa-quickstart \
        --extension='security-jpa,jdbc-postgresql,resteasy-reactive,hibernate-orm-panache' \
        --no-code
    cd security-jpa-quickstart
    Copy to Clipboard Toggle word wrap

    要创建 Gradle 项目,请添加 --gradle--gradle-kotlin-dsl 选项。

    有关如何安装和使用 Quarkus CLI 的更多信息,请参阅 Quarkus CLI 指南。

  • 使用 Maven:

    mvn io.quarkus.platform:quarkus-maven-plugin:3.8.5:create \
        -DprojectGroupId=org.acme \
        -DprojectArtifactId=security-jpa-quickstart \
        -Dextensions='security-jpa,jdbc-postgresql,resteasy-reactive,hibernate-orm-panache' \
        -DnoCode
    cd security-jpa-quickstart
    Copy to Clipboard Toggle word wrap

    要创建 Gradle 项目,请添加 -DbuildTool=gradle-DbuildTool=gradle-kotlin-dsl 选项。

对于 Windows 用户:

  • 如果使用 cmd,(不使用反向斜杠 \ 并将所有内容放在同一行中)
  • 如果使用 Powershell,使用双引号换 -D 参数,例如 "-DprojectArtifactId=security-jpa-quickstart"

    • 要将 Jakarta Persistence 扩展添加到现有 Maven 项目中,请完成以下步骤之一:

      • 要使用 Hibernate ORM 将 Security Jakarta Persistence 扩展添加到现有 Maven 项目中,请从项目基础目录运行以下命令:

        • 使用 Quarkus CLI:

          quarkus extension add security-jpa
          Copy to Clipboard Toggle word wrap
        • 使用 Maven:

          ./mvnw quarkus:add-extension -Dextensions='security-jpa'
          Copy to Clipboard Toggle word wrap
        • 使用 Gradle :

          ./gradlew addExtension --extensions='security-jpa'
          Copy to Clipboard Toggle word wrap

1.3.2. 验证 quarkus-security-jpa 依赖项

运行上述命令以创建 Maven 项目后,验证 quarkus-security-jpa 依赖项是否已添加到项目构建 XML 文件中。

  • 要验证 quarkus-security-jpa 扩展,请检查以下配置:

    • 使用 Maven:

      <dependency>
          <groupId>io.quarkus</groupId>
          <artifactId>quarkus-security-jpa</artifactId>
      </dependency>
      Copy to Clipboard Toggle word wrap
    • 使用 Gradle :

      implementation("io.quarkus:quarkus-security-jpa")
      Copy to Clipboard Toggle word wrap

1.4. 编写应用程序

  • 保护 API 端点,以决定您可以使用以下方法之一访问应用程序:

    • 实施 /api/public 端点,以允许所有用户访问应用。在 Java 源代码中添加常规 Jakarta REST 资源,如以下代码片段所示:

      package org.acme.security.jpa;
      
      import jakarta.annotation.security.PermitAll;
      import jakarta.ws.rs.GET;
      import jakarta.ws.rs.Path;
      import jakarta.ws.rs.Produces;
      import jakarta.ws.rs.core.MediaType;
      
      @Path("/api/public")
      public class PublicResource {
      
          @GET
          @PermitAll
          @Produces(MediaType.TEXT_PLAIN)
          public String publicResource() {
              return "public";
         }
      }
      Copy to Clipboard Toggle word wrap
    • 实施 /api/admin 端点,该端点只能被具有 admin 角色的用户访问。/api/admin 端点的源代码类似,而是使用 @RolesAllowed 注释来确保仅授予 admin 角色的用户可以访问端点。使用以下 @RolesAllowed 注释添加 Jakarta REST 资源:

      package org.acme.security.jpa;
      
      import jakarta.annotation.security.RolesAllowed;
      import jakarta.ws.rs.GET;
      import jakarta.ws.rs.Path;
      import jakarta.ws.rs.Produces;
      import jakarta.ws.rs.core.MediaType;
      
      @Path("/api/admin")
      public class AdminResource {
      
          @GET
          @RolesAllowed("admin")
          @Produces(MediaType.TEXT_PLAIN)
          public String adminResource() {
               return "admin";
          }
      }
      Copy to Clipboard Toggle word wrap
    • 实施 /api/users/me 端点,该端点只能被拥有 用户角色 的用户访问。使用 SecurityContext 访问当前验证的 Principal 用户,并返回其用户名,所有这些用户名都从数据库检索。

      package org.acme.security.jpa;
      
      import jakarta.annotation.security.RolesAllowed;
      import jakarta.inject.Inject;
      import jakarta.ws.rs.GET;
      import jakarta.ws.rs.Path;
      import jakarta.ws.rs.core.Context;
      import jakarta.ws.rs.core.SecurityContext;
      
      @Path("/api/users")
      public class UserResource {
      
          @GET
          @RolesAllowed("user")
          @Path("/me")
          public String me(@Context SecurityContext securityContext) {
              return securityContext.getUserPrincipal().getName();
          }
      }
      Copy to Clipboard Toggle word wrap

1.5. 定义用户实体

  • 现在,您可以通过向 用户 实体添加注解,如以下代码片段中所述,描述在模型中存储安全信息的方式:
package org.acme.security.jpa;

import jakarta.persistence.Entity;
import jakarta.persistence.Table;

import io.quarkus.hibernate.orm.panache.PanacheEntity;
import io.quarkus.elytron.security.common.BcryptUtil;
import io.quarkus.security.jpa.Password;
import io.quarkus.security.jpa.Roles;
import io.quarkus.security.jpa.UserDefinition;
import io.quarkus.security.jpa.Username;

@Entity
@Table(name = "test_user")
@UserDefinition 
1

public class User extends PanacheEntity {
    @Username 
2

    public String username;
    @Password 
3

    public String password;
    @Roles 
4

    public String role;

    /**
     * Adds a new user to the database
     * @param username the username
     * @param password the unencrypted password (it is encrypted with bcrypt)
     * @param role the comma-separated roles
     */
    public static void add(String username, String password, String role) { 
5

        User user = new User();
        user.username = username;
        user.password = BcryptUtil.bcryptHash(password);
        user.role = role;
        user.persist();
    }
}
Copy to Clipboard Toggle word wrap

只有在单个实体标上 @UserDefinition 注解时,quarkus-security-jpa 扩展才会初始化。

1
@UserDefinition 注释必须存在于单一实体上,可以是常规 Hibernate ORM 实体,也可以是带有 Panache 实体的 Hibernate ORM。
2
表示用于用户名的字段。
3
表示用于密码的字段。默认情况下,它使用 bcrypt-hashed 密码。您可以将其配置为使用纯文本或自定义密码。
4
表示添加到目标主体表示属性中的以逗号分隔的角色列表。
5
允许我们在使用适当的 bcrypt 哈希哈希哈希时添加用户。
注意

不要忘记设置 Panache 和 PostgreSQL JDBC 驱动程序,请参阅 使用 Panache 设置和配置 Hibernate ORM

1.6. 配置应用程序

  1. 通过将 quarkus.http.auth.basic 属性设置为 true 来启用内置的 Quarkus 基本身份验证 机制:

    quarkus.http.auth.basic=true

    注意

    当需要安全访问时,且不需要启用其他身份验证机制,Quarkus 的内置 基本身份验证 是回退身份验证机制。因此,在本教程中,您不需要将属性 quarkus.http.auth.basic 设置为 true

  2. application.properties 文件中至少配置一个数据源,以便 quarkus-security-jpa 扩展可以访问您的数据库。例如:

    quarkus.http.auth.basic=true
    
    quarkus.datasource.db-kind=postgresql
    quarkus.datasource.username=quarkus
    quarkus.datasource.password=quarkus
    quarkus.datasource.jdbc.url=jdbc:postgresql:security_jpa
    
    quarkus.hibernate-orm.database.generation=drop-and-create
    Copy to Clipboard Toggle word wrap
  3. 要使用用户和角色初始化数据库,请实施 启动 类,如以下代码片段中所述:
package org.acme.security.jpa;

import jakarta.enterprise.event.Observes;
import jakarta.inject.Singleton;
import jakarta.transaction.Transactional;

import io.quarkus.runtime.StartupEvent;


@Singleton
public class Startup {
    @Transactional
    public void loadUsers(@Observes StartupEvent evt) {
        // reset and load all test users
        User.deleteAll();
        User.add("admin", "admin", "admin");
        User.add("user", "user", "user");
    }
}
Copy to Clipboard Toggle word wrap

前面的示例演示了应用程序如何受到指定数据库提供的保护和身份。

重要

在生产环境中,请勿存储纯文本密码。因此,quarkus-security-jpa 默认使用 bcrypt-hashed 密码。

1.7. 使用 PostgreSQL 的 Dev Services 测试应用程序

在生产模式下运行应用程序之前,请先使用 PostgreSQL 的 Dev Services for PostgreSQL 完成应用程序的集成测试和原生模式。

首先,在您的测试项目中添加以下依赖项:

  • 使用 Maven:

    <dependency>
        <groupId>io.rest-assured</groupId>
        <artifactId>rest-assured</artifactId>
        <scope>test</scope>
    </dependency>
    Copy to Clipboard Toggle word wrap
  • 使用 Gradle :

    testImplementation("io.rest-assured:rest-assured")
    Copy to Clipboard Toggle word wrap
  • 以 dev 模式运行您的应用程序:
  • 使用 Quarkus CLI:

    quarkus dev
    Copy to Clipboard Toggle word wrap
  • 使用 Maven:

    ./mvnw quarkus:dev
    Copy to Clipboard Toggle word wrap
  • 使用 Gradle :

    ./gradlew --console=plain quarkusDev
    Copy to Clipboard Toggle word wrap
  • 以下属性配置演示了如何使 PostgreSQL 测试仅在生产(prod)模式下运行。在这种情况下,PostgreSQL 的 Dev Services 会启动并配置 PostgreSQL 测试容器。
%prod.quarkus.datasource.db-kind=postgresql
%prod.quarkus.datasource.username=quarkus
%prod.quarkus.datasource.password=quarkus
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql:elytron_security_jpa

quarkus.hibernate-orm.database.generation=drop-and-create
Copy to Clipboard Toggle word wrap
  • 如果您添加了 %prod. 配置集前缀,则数据源属性对 PostgreSQL 的 Dev Services 不可见,且仅在生产模式下运行的应用程序中看到。
  • 要编写集成测试,请使用以下代码示例:
package org.acme.security.jpa;

import static io.restassured.RestAssured.get;
import static io.restassured.RestAssured.given;
import static org.hamcrest.core.Is.is;

import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class JpaSecurityRealmTest {

    @Test
    void shouldAccessPublicWhenAnonymous() {
        get("/api/public")
                .then()
                .statusCode(HttpStatus.SC_OK);

    }

    @Test
    void shouldNotAccessAdminWhenAnonymous() {
        get("/api/admin")
                .then()
                .statusCode(HttpStatus.SC_UNAUTHORIZED);

    }

    @Test
    void shouldAccessAdminWhenAdminAuthenticated() {
        given()
                .auth().preemptive().basic("admin", "admin")
                .when()
                .get("/api/admin")
                .then()
                .statusCode(HttpStatus.SC_OK);

    }

    @Test
    void shouldNotAccessUserWhenAdminAuthenticated() {
        given()
                .auth().preemptive().basic("admin", "admin")
                .when()
                .get("/api/users/me")
                .then()
                .statusCode(HttpStatus.SC_FORBIDDEN);
    }

    @Test
    void shouldAccessUserAndGetIdentityWhenUserAuthenticated() {
        given()
                .auth().preemptive().basic("user", "user")
                .when()
                .get("/api/users/me")
                .then()
                .statusCode(HttpStatus.SC_OK)
                .body(is("user"));
    }
}
Copy to Clipboard Toggle word wrap

正如您在此代码示例中看到的,您不需要从测试代码启动测试容器。

注意

当您以 dev 模式启动应用程序时,PostgreSQL 的 Dev Services 会启动一个 PostgreSQL dev 模式容器,以便您可以开始开发应用程序。在开发应用程序时,您可以使用 Continuous Testing 功能单独添加和运行测试。在提供与 dev 模式容器不冲突的独立 PostgreSQL 测试容器时,用于 PostgreSQL 的 dev Services 支持测试。

1.7.1. 使用 curl 或浏览器来测试应用程序

  • 使用以下示例启动 PostgreSQL 服务器:
docker run --rm=true --name security-getting-started -e POSTGRES_USER=quarkus \
           -e POSTGRES_PASSWORD=quarkus -e POSTGRES_DB=elytron_security_jpa \
           -p 5432:5432 postgres:14.1
Copy to Clipboard Toggle word wrap

1.7.2. 编译并运行应用程序

  • 使用以下方法之一编译并运行 Quarkus 应用程序:

    • JVM 模式

      1. 编译应用程序:

        • 使用 Quarkus CLI:

          quarkus build
          Copy to Clipboard Toggle word wrap
        • 使用 Maven:

          ./mvnw install
          Copy to Clipboard Toggle word wrap
        • 使用 Gradle :

          ./gradlew build
          Copy to Clipboard Toggle word wrap
      2. 运行应用程序:

        java -jar target/quarkus-app/quarkus-run.jar
        Copy to Clipboard Toggle word wrap
    • 原生模式

      1. 编译应用程序:

        • 使用 Quarkus CLI:

          quarkus build --native
          Copy to Clipboard Toggle word wrap
        • 使用 Maven:

          ./mvnw install -Dnative
          Copy to Clipboard Toggle word wrap
        • 使用 Gradle :

          ./gradlew build -Dquarkus.package.type=native
          Copy to Clipboard Toggle word wrap
      2. 运行应用程序:

        ./target/security-jpa-quickstart-1.0.0-SNAPSHOT-runner
        Copy to Clipboard Toggle word wrap

1.7.3. 访问并测试应用程序安全性

当应用运行时,您可以使用以下 Curl 命令之一访问其端点。

  • 匿名连接到受保护的端点:

    $ curl -i -X GET http://localhost:8080/api/public
    
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: text/plain;charset=UTF-8
    
    public
    Copy to Clipboard Toggle word wrap
  • 匿名连接到受保护的端点:

    $ curl -i -X GET http://localhost:8080/api/admin
    
    HTTP/1.1 401 Unauthorized
    Content-Length: 14
    Content-Type: text/html;charset=UTF-8
    WWW-Authenticate: Basic
    
    Not authorized
    Copy to Clipboard Toggle word wrap
  • 以授权用户身份连接到受保护的端点:

    $ curl -i -X GET -u admin:admin http://localhost:8080/api/admin
    
    HTTP/1.1 200 OK
    Content-Length: 5
    Content-Type: text/plain;charset=UTF-8
    
    admin
    Copy to Clipboard Toggle word wrap

您还可以使用浏览器访问相同的端点 URL。

注意

如果您使用浏览器匿名连接到受保护的资源,则会显示基本身份验证表单,提示您输入凭证。

1.7.4. 结果

当您提供授权用户的凭证时,如 admin:admin,Jakarta Persistence 安全扩展会验证和加载该用户的角色。admin 用户有权访问受保护的资源。

如果资源通过 @RolesAllowed ("user") 进行保护,则用户 admin 不会被授权访问该资源,因为它没有分配给"user"角色,如下例所示:

$ curl -i -X GET -u admin:admin http://localhost:8080/api/users/me

HTTP/1.1 403 Forbidden
Content-Length: 34
Content-Type: text/html;charset=UTF-8

Forbidden
Copy to Clipboard Toggle word wrap

最后,名为 user 的用户被授权,安全上下文包含主体详情,例如 username。

$ curl -i -X GET -u user:user http://localhost:8080/api/users/me

HTTP/1.1 200 OK
Content-Length: 4
Content-Type: text/plain;charset=UTF-8

user
Copy to Clipboard Toggle word wrap

1.8. 下一步是什么

您已成功了解了如何创建和测试安全的 Quarkus 应用程序。这可以通过将 Quarkus 中的内置 基本身份验证 与 Jakarta Persistence 身份提供程序集成来实现。

完成本教程后,您可以在 Quarkus 中探索更高级的安全机制。以下信息演示了如何使用 OpenID Connect 来保护对 Quarkus 端点的单点登录访问:

1.9. 参考

您可以将应用程序配置为使用 Jakarta Persistence 来存储用户身份。

Quarkus 提供 Jakarta Persistence 身份提供程序,类似于 JDBC 身份提供程序。Jakarta Persistence 适用于基于 BasicForm 的 Quarkus 安全机制,这需要用户名和密码凭证。

Jakarta Persistence IdentityProvider 创建一个 SecurityIdentity 实例。在用户身份验证过程中,此实例用于验证和授权访问请求。

有关实际示例,请参阅开始使用基本身份验证和 Jakarta Persistence 指南。

2.1. Jakarta Persistence 实体规格

Quarkus 安全提供了一个 Jakarta Persistence 集成,用于收集用户名、密码和角色,并将它们存储在 Jakarta Persistence 数据库实体中。

以下 Jakarta Persistence 实体规格演示了如何将用户信息存储在 Jakarta Persistence 实体中,并正确映射,以便 Quarkus 可以从数据库检索此信息。

  • @UserDefinition 注释必须存在于 Jakarta Persistence 实体上,无论是否使用 Panache 简化了 Hibernate ORM
  • @Username@Password 字段类型始终是 String
  • @Roles 字段必须是 String,Collection<String>, 或 Collection<X >,其中 X 是一个实体类,带有标记为 @RolesValueString 字段。
  • 每个 String role 元素类型被解析为以逗号分隔的角色列表。

以下示例演示了在 用户 实体中添加注解来存储安全信息:

package org.acme.security.jpa;

import jakarta.persistence.Entity;
import jakarta.persistence.Table;

import io.quarkus.hibernate.orm.panache.PanacheEntity;
import io.quarkus.elytron.security.common.BcryptUtil;
import io.quarkus.security.jpa.Password;
import io.quarkus.security.jpa.Roles;
import io.quarkus.security.jpa.UserDefinition;
import io.quarkus.security.jpa.Username;

@Entity
@Table(name = "test_user")
@UserDefinition 
1

public class User extends PanacheEntity {
    @Username 
2

    public String username;
    @Password 
3

    public String password;
    @Roles 
4

    public String role;

    /**
     * Adds a new user to the database
     * @param username the username
     * @param password the unencrypted password (it is encrypted with bcrypt)
     * @param role the comma-separated roles
     */
    public static void add(String username, String password, String role) { 
5

        User user = new User();
        user.username = username;
        user.password = BcryptUtil.bcryptHash(password);
        user.role = role;
        user.persist();
    }
}
Copy to Clipboard Toggle word wrap

只有在单个实体标上 @UserDefinition 标注时,quarkus-security-jpa 扩展才会初始化。

1
@UserDefinition 注释必须存在于单一实体上,可以是常规 Hibernate ORM 实体,也可以是带有 Panache 实体的 Hibernate ORM。
2
表示用于用户名的字段。
3
表示用于密码的字段。默认情况下,quarkus-security-jpa 使用 bcrypt-hashed 密码,也可以改为配置纯文本或自定义密码。
4
这表示添加到目标主体表示属性中的以逗号分隔的角色列表。
5
这个方法允许您在带有正确 bcrypt 哈希的哈希密码时添加用户。

2.2. Jakarta Persistence 实体作为角色存储

使用以下示例将角色存储在另一个 Jakarta Persistence 实体中:

@UserDefinition
@Table(name = "test_user")
@Entity
public class User extends PanacheEntity {
    @Username
    public String name;

    @Password
    public String pass;

    @ManyToMany
    @Roles
    public List<Role> roles = new ArrayList<>();
}

@Entity
public class Role extends PanacheEntity {

    @ManyToMany(mappedBy = "roles")
    public List<User> users;

    @RolesValue
    public String role;
}
Copy to Clipboard Toggle word wrap
注意

本例演示了存储和访问角色。要更新现有用户或创建新用户,请为 公共 List<Role> 角色 标上 @Cascade (CascadeType.ALL),或选择特定的 CascadeType

2.3. 密码存储和哈希

使用 Quarkus 开发应用程序时,您可以决定如何管理密码存储和哈希。您可以保留 Quarkus 的默认密码和哈希设置,也可以手动哈希密码。

使用默认选项时,密码以 Modular Crypt 格式 (MCF)下的 bcrypt 存储和哈希。在使用 MCF 时,哈希算法、迭代数和 salt 作为散列值的一部分存储。因此,我们不需要专用列来保留它们。

注意

在加密中,salt 是随机数据的名称,用作哈希数据、密码或密码短语的单向功能的额外输入。

要代表存储在由不同算法哈希的数据库中的密码,请创建一个实现 org.wildfly.security.password.PasswordProvider 的类,如下例所示。

下列代码片段演示了如何设置自定义密码提供程序,该提供程序表示使用 SHA256 哈希算法散列化的密码。

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

import io.quarkus.security.jpa.Password;
import io.quarkus.security.jpa.PasswordType;
import io.quarkus.security.jpa.Roles;
import io.quarkus.security.jpa.UserDefinition;
import io.quarkus.security.jpa.Username;

@UserDefinition
@Table(name = "test_user")
@Entity
public class CustomPasswordUserEntity {
    @Id
    @GeneratedValue
    public Long id;

    @Column(name = "username")
    @Username
    public String name;

    @Column(name = "password")
    @Password(value = PasswordType.CUSTOM, provider = CustomPasswordProvider.class)
    public String pass;

    @Roles
    public String role;
}
Copy to Clipboard Toggle word wrap
import jakarta.xml.bind.DatatypeConverter;

import org.wildfly.security.password.Password;
import org.wildfly.security.password.interfaces.SimpleDigestPassword;

import io.quarkus.security.jpa.PasswordProvider;

public class CustomPasswordProvider implements PasswordProvider {
    @Override
    public Password getPassword(String passwordInDatabase) {
        byte[] digest = DatatypeConverter.parseHexBinary(passwordInDatabase);

        // Let the security runtime know that this passwordInDatabase is hashed by using the SHA256 hashing algorithm
        return SimpleDigestPassword.createRaw(SimpleDigestPassword.ALGORITHM_SIMPLE_DIGEST_SHA_256, digest);
    }
}
Copy to Clipboard Toggle word wrap
提示

要快速创建哈希密码,请使用 String BcryptUtil.bcryptHash (字符串密码), 默认为在 10 迭代中创建随机 salt 和哈希。此方法还允许指定所用的迭代和 salt 数。

警告

对于在生产环境中运行的应用程序,请不要将密码存储为纯文本。

但是,在测试环境中操作时,可以使用 @Password (PasswordType.CLEAR) 注释以纯文本形式存储密码。

提示

支持 Hibernate 多租户,您可以在启用了多租户的情况下将用户实体存储在持久性单元中。但是,如果您的 io.quarkus.hibernate.orm.runtime.tenant.TenantResolver 必须访问 io.vertx.ext.web.RoutingContext 来解析请求详情,您必须禁用主动身份验证。有关主动身份验证的更多信息,请参阅 Quarkus 主动身份验证 指南。

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

Expand

Configuration 属性

类型

default

lock quarkus.security-jpa.persistence-unit-name

选择 Hibernate ORM Persistence 单元。如果没有指定值,则使用默认的持久性单元。

环境变量: QUARKUS_SECURITY_zFCP_PERSISTENCE_UNIT_NAME

string

<default>

2.4. 参考

法律通告

Copyright © 2025 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

Theme

© 2026 Red Hat