认证与权限安全
你当前正在浏览历史版本 Vert.x 5.1.10 的文档。 访问本页面的 最新版本。

MongoDB 身份认证与授权提供者 (vertx-auth-mongo)

该组件提供了基于 Vert.x MongoClient 的 AuthenticationProvider 认证与授权实现,支持在 MongoDB 文档数据库中完成用户身份核验与权限评估。

要在项目中使用该组件,请在构建描述文件的 dependencies 区域添加以下依赖:

  • Maven(在 pom.xml 中):

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-auth-mongo</artifactId>
  <version>5.1.10</version>
</dependency>
  • Gradle(在 build.gradle 文件中):

compile 'io.vertx:vertx-auth-mongo:5.1.10'

创建提供者前首先需要一个 MongoClient 实例。有关如何创建与配置该客户端,请参阅 MongoClient 官方文档。

就绪后,按如下方式创建 MongoAuthentication 实例:

MongoClient client = MongoClient.createShared(vertx, mongoClientConfig);
MongoAuthenticationOptions options = new MongoAuthenticationOptions();
MongoAuthentication authenticationProvider =
  MongoAuthentication.create(client, options);

获得实例后,即可像使用常规 AuthenticationProvider 一样进行身份验证与权限判定。

开箱即用的默认配置假定使用名为 "user" 的集合,其中用户名存储并读取自 "username" 字段,密码哈希存储在 "password" 字段。

为防止用户名重复插入,你的 "user" 集合应为 "username" 字段创建唯一索引。在 MongoDB 服务端执行如下脚本:

db.user.createIndex( { username: 1 }, { unique: true } )

必须创建唯一索引的核心原因在于:由于 MongoDB 自身特性,先通过查询判断用户名是否存在然后再插入文档的操作不具备原子性。借助唯一索引,系统在尝试插入重复行时由数据库直接报错拦截。

如果需要适配现有的数据库结构,你可以通过以下方法灵活修改集合名与字段名默认值:

默认实现假定密码按照通用的 HashingStrategy 策略存储在数据库中(即 Salt 盐值与哈希算法元数据内嵌在密码哈希串内部)。

数据隐私合规说明 (GDPR)

通用数据保护条例(GDPR)是欧盟的一项通用法律规范。它高于各成员国的本土数据保护法,并对既有规范进行了扩展。本节绝非条例的详尽法律解释,而是简明阐述该组件如何遵循合规要求。企业若违反相关规定,最高可能面临年营业额 4% 或 2000 万欧元的巨额罚款。因此,Vert.x 致力于确保开发者在使用认证组件时具备合规基础。

法律核心术语定义:

  • 数据主体(Data Subject):个人数据所关联的自然人(如终端用户)

  • 个人数据(Personal Data):与已识别或可识别自然人相关的任何信息

  • 数据处理(Data Processing):对个人数据执行的任何操作(无论人工或自动化)

  • 控制者(Controller):决定数据处理目的与方式的实体(即企业组织)

  • 处理者(Processors):代表控制者处理数据的实体(如云计算服务商)

GDPR 核心权利与要求包括:

  • “被遗忘权”——擦除权(Right to erasure)

  • 限制处理权——将用户档案标记为限制处理(Right to restriction of processing)

  • 数据可携权——导出个人数据(Right to portability)

  • 更正权——允许用户修改个人资料(Right to rectification)

  • 知情与访问权——查看个人所有数据(Right to access)

  • 显式同意复选框

  • 年龄限制核验

  • 数据最小化原则——及时销毁无用数据

本认证模块在设计上不直接存储任何属于数据主体的可识别个人数据,因而天然满足 GDPR 规范。数据库记录中唯一的标识是用户名(username),它本身并不强制与任何现实个人信息绑定。

要在应用中管理用户的个人数据,你应该建立独立的业务模型,并将用户名作为外键关联至你的业务数据。建议在业务表中维护一个布尔标记字段,用于在用户行使“限制处理权”时将该个人数据标记为限制状态;这意味着在标记为 true 时,系统不得对其执行非必要处理(如批量发送营销邮件)。

“擦除权”并不代表必须抹去系统内的所有业务记录。例如在银行系统中,用户行使被遗忘权不能用于抹消未偿还的贷款或债务。你被允许保留业务记录,但必须抹除所有可识别的个人隐私数据。在使用 Vert.x Auth Mongo 时,你可以清理业务资料表,只要确保保留的用户名无法反向关联至自然人身份即可。

请特别注意:合规性在数据备份与归档中同样必须得到保证!建议将业务归档与擦除操作记录分别独立存档,以便能够单独审计与重放。

执行身份验证

使用该实现执行身份验证时,认证信息中必须包含 username 与 password 字段:

Credentials credentials =
  new UsernamePasswordCredentials("tim", "sausages");

authProvider.authenticate(credentials)
  .onSuccess(user -> System.out.println("用户:" + user.principal()))
  .onFailure(err -> {
    // 认证失败!
  });

如果你定制了凭据字段名,可以通过以下方法获取配置的属性名: getUsernameCredentialField 以及 getPasswordCredentialField。

权限授权:用户-角色-权限模型 (RBAC)

尽管 Vert.x Auth 本身并不强制固定权限模型(权限在底层仅被视作透明字符串),但该实现采用了广为人知的标准“用户 / 角色 / 权限”体系:一个用户可以拥有零个或多个角色,一个角色可以包含零个或多个具体权限。

mongoAuthZ.getAuthorizations(user)
  .onSuccess(v -> {
    if (PermissionBasedAuthorization.create("commit_code").match(user)) {
      // 拥有 commit_code 权限!
    }
  });

若需校验用户是否拥有某个特定 角色(Role),直接使用 RoleBasedAuthorization 即可:

mongoAuthZ.getAuthorizations(user)
  .onSuccess(v -> {
    if (RoleBasedAuthorization.create("manager").match(user)) {
      // 拥有 manager 角色!
    }
  });