此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Vault 3.1.2spring-doc.cadn.net.cn

Vault 存储库

使用VaultTemplate映射到 Java 类的响应允许执行基本数据作,如读取、写入和删除。 Vault 存储库在 Vault 之上应用 Spring Data 的存储库概念。 Vault 存储库公开了基本的 CRUD 功能,并支持使用限制标识符属性、分页和排序的谓词进行查询派生。 文件库存储库使用键/值密钥引擎功能来保存和查询数据。 从版本 2.4 开始, Spring Vault 可以使用额外的键/值版本 2 秘密引擎,实际的秘密引擎版本是在运行时发现的。spring-doc.cadn.net.cn

版本控制的键/值 Secret 引擎中的 Deletes 使用DELETE操作。机密不会通过以下方式销毁CrudRepository.delete(…).
Spring Data Commons 参考文档中阅读有关 Spring Data Repositories 的更多信息。 参考文档将为您提供 Spring Data 存储库的介绍。

用法

要访问存储在 Vault 中的域实体,您可以利用存储库支持来大大简化这些实体的实施。spring-doc.cadn.net.cn

示例 1.示例 Credentials 实体
@Secret
class Credentials {

  @Id String id;
  String password;
  String socialSecurityNumber;
  Address address;
}

我们这里有一个非常简单的 domain 对象。 请注意,它有一个名为id注解org.springframework.data.annotation.Id以及@Secret注解。 这两个负责创建用于将对象作为 JSON 保存在 Vault 中的实际密钥。spring-doc.cadn.net.cn

注释 的属性@Id以及那些被命名为id被视为标识符属性。 带有注释的 Comments 比其他 Comments 更受欢迎。

下一步是声明使用 domain 对象的存储库接口。spring-doc.cadn.net.cn

示例 2.的基本存储库界面Credentials实体
interface CredentialsRepository extends CrudRepository<Credentials, String> {

}

随着我们的存储库扩展CrudRepository它提供了基本的 CRUD 和查询方法。 Vault 存储库需要 Spring Data 组件。 确保包括spring-data-commonsspring-data-keyvalueartifacts 的 artifacts 中。spring-doc.cadn.net.cn

实现此目的的最简单方法是设置依赖项管理并将工件添加到pom.xml:spring-doc.cadn.net.cn

然后将以下内容添加到pom.xmldependencies 部分。spring-doc.cadn.net.cn

例 3.使用 Spring Data BOM
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-bom</artifactId>
      <version>2023.1.2</version>
      <scope>import</scope>
      <type>pom</type>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>

  <!-- other dependency elements omitted -->

  <dependency>
    <groupId>org.springframework.vault</groupId>
    <artifactId>spring-vault-core</artifactId>
    <version>3.2.0-SNAPSHOT</version>
  </dependency>

  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-keyvalue</artifactId>
    <!-- Version inherited from the BOM -->
  </dependency>

</dependencies>

我们需要在两者之间将事物粘合在一起的是相应的 Spring 配置。spring-doc.cadn.net.cn

示例 4.用于 Vault 存储库的 JavaConfig
@Configuration
@EnableVaultRepositories
class ApplicationConfig {

  @Bean
  VaultTemplate vaultTemplate() {
    return new VaultTemplate(…);
  }
}

根据上面的设置,我们可以继续注入CredentialsRepository融入我们的组件中。spring-doc.cadn.net.cn

例 5.访问 Person 实体
@Autowired CredentialsRepository repo;

void basicCrudOperations() {

  Credentials creds = new Credentials("heisenberg", "327215", "AAA-GG-SSSS");
  rand.setAddress(new Address("308 Negra Arroyo Lane", "Albuquerque", "New Mexico", "87104"));

  repo.save(creds);                                        (1)

  repo.findOne(creds.getId());                             (2)

  repo.count();                                            (3)

  repo.delete(creds);                                      (4)
}
1 存储 的属性Credentials在 Vault Hash 中,具有密钥模式keyspace/id,在本例中credentials/heisenberg中,在键值 Secret Secrets 引擎中。
2 使用提供的 ID 检索存储在keyspace/id.
3 计算@SecretCredentials.
4 从 Vault 中删除给定对象的密钥。

对象到文件库的 JSON 映射

Vault 存储库使用 JSON 作为交换格式将对象存储在 Vault 中。 JSON 和实体之间的对象映射由VaultConverter. 转换器读取和写入SecretDocument,其中包含来自VaultResponse.VaultResponse从 Vault 中读取,并且 Jackson 将正文反序列化为MapStringObject. 默认的VaultConverterimplementation 会读取Mapwith 嵌套值,ListMap对象并将其转换为实体,反之亦然。spring-doc.cadn.net.cn

鉴于Credentialstype 的 default 映射如下:spring-doc.cadn.net.cn

{
  "_class": "org.example.Credentials",                 (1)
  "password": "327215",                                (2)
  "socialSecurityNumber": "AAA-GG-SSSS",
  "address": {                                         (3)
    "street": "308 Negra Arroyo Lane",
    "city": "Albuquerque",
    "state": "New Mexico",
    "zip": "87104"
  }
}
1 _classattribute 包含在根级别以及任何嵌套接口或抽象类型中。
2 简单属性值按 path 进行映射。
3 复杂类型的属性映射为嵌套对象。
@Idproperty 必须映射到String.
表 1.默认映射规则
类型 样本 映射值

简单类型
(例如。字符串)spring-doc.cadn.net.cn

字符串 firstname = “Walter”;spring-doc.cadn.net.cn

“firstname”: “沃尔特”spring-doc.cadn.net.cn

复杂型
(例如。地址)spring-doc.cadn.net.cn

地址 adress = 新地址(“308 Negra Arroyo Lane”);spring-doc.cadn.net.cn

“address”: { “street”: “308 Negra Arroyo Lane” }spring-doc.cadn.net.cn

简单类型列表
spring-doc.cadn.net.cn

List<String> 昵称 = asList(“walt”, “heisenberg”);spring-doc.cadn.net.cn

“昵称”: [“Walt”, “Heisenberg”]spring-doc.cadn.net.cn

简单类型的映射
spring-doc.cadn.net.cn

Map<String, 整数> atts = asMap(“age”, 51)spring-doc.cadn.net.cn

“atts” : {“age” : 51}spring-doc.cadn.net.cn

复杂类型列表
spring-doc.cadn.net.cn

List<Address> addresses = asList(new Address(“308...spring-doc.cadn.net.cn

“address”: [{ “street”: “308 Negra Arroyo Lane” }, ...]spring-doc.cadn.net.cn

您可以通过注册ConverterVaultCustomConversions. 这些转换器可以负责从/转换为类型,例如LocalDate以及SecretDocument而第一个适合将简单属性转换为其 JSON 表示形式,最后一个复杂类型。 第二个选项提供对生成的SecretDocument. 将对象写入Vault将删除内容并重新创建整个条目,因此未映射的数据将丢失。spring-doc.cadn.net.cn

查询和查询方法

Query methods 允许从方法名称自动派生简单查询。 Vault 没有查询引擎,但需要直接访问 HTTP 上下文路径。 Vault 查询方法将 Vault 的 API 可能性转换为查询。 查询方法执行在上下文路径下列出子项,对 Id 应用筛选,(可选)使用 offset/limit 限制 Id 流,并在获取结果后应用排序。spring-doc.cadn.net.cn

例 6.示例存储库查询方法
interface CredentialsRepository extends CrudRepository<Credentials, String> {

  List<Credentials> findByIdStartsWith(String prefix);
}
Vault 存储库的查询方法仅支持在@Id财产。

以下是 Vault 支持的关键字概述。spring-doc.cadn.net.cn

表 2.查询方法支持的关键字
关键词 样本

After,GreaterThanspring-doc.cadn.net.cn

findByIdGreaterThan(String id)spring-doc.cadn.net.cn

GreaterThanEqualspring-doc.cadn.net.cn

findByIdGreaterThanEqual(String id)spring-doc.cadn.net.cn

Before,LessThanspring-doc.cadn.net.cn

findByIdLessThan(String id)spring-doc.cadn.net.cn

LessThanEqualspring-doc.cadn.net.cn

findByIdLessThanEqual(String id)spring-doc.cadn.net.cn

Betweenspring-doc.cadn.net.cn

findByIdBetween(String from, String to)spring-doc.cadn.net.cn

Inspring-doc.cadn.net.cn

findByIdIn(Collection ids)spring-doc.cadn.net.cn

NotInspring-doc.cadn.net.cn

findByIdNotIn(Collection ids)spring-doc.cadn.net.cn

Like,StartingWith,EndingWithspring-doc.cadn.net.cn

findByIdLike(String id)spring-doc.cadn.net.cn

NotLike,IsNotLikespring-doc.cadn.net.cn

findByIdNotLike(String id)spring-doc.cadn.net.cn

Containingspring-doc.cadn.net.cn

findByFirstnameContaining(String id)spring-doc.cadn.net.cn

NotContainingspring-doc.cadn.net.cn

findByFirstnameNotContaining(String name)spring-doc.cadn.net.cn

Regexspring-doc.cadn.net.cn

findByIdRegex(String id)spring-doc.cadn.net.cn

(No keyword)spring-doc.cadn.net.cn

findById(String name)spring-doc.cadn.net.cn

Notspring-doc.cadn.net.cn

findByIdNot(String id)spring-doc.cadn.net.cn

Andspring-doc.cadn.net.cn

findByLastnameAndFirstnamespring-doc.cadn.net.cn

Orspring-doc.cadn.net.cn

findByLastnameOrFirstnamespring-doc.cadn.net.cn

Is,Equalsspring-doc.cadn.net.cn

findByFirstname,findByFirstnameIs,findByFirstnameEqualsspring-doc.cadn.net.cn

Top,Firstspring-doc.cadn.net.cn

findFirst10ByFirstname,findTop5ByFirstnamespring-doc.cadn.net.cn

排序和分页

查询方法支持排序和分页,方法是在内存中选择从 Vault 上下文路径中检索到的子列表(偏移量/限制)Id。 与查询方法谓词不同,排序 has 不限于特定字段。 在 Id 筛选后应用未分页排序,并从 Vault 获取所有生成的密钥。 这样,查询方法仅获取也作为结果的一部分返回的结果。spring-doc.cadn.net.cn

使用分页和排序需要在过滤 Id 之前获取密钥,这会影响性能。 排序和分页保证即使 Vault 返回的 Id 的自然顺序发生变化,也会返回相同的结果。 因此,首先从 Vault 获取所有 ID,然后应用排序,然后进行过滤和偏移/限制。spring-doc.cadn.net.cn

例 7.分页和排序存储库
interface CredentialsRepository extends PagingAndSortingRepository<Credentials, String> {

  List<Credentials> findTop10ByIdStartsWithOrderBySocialSecurityNumberDesc(String prefix);

  List<Credentials> findByIdStarts(String prefix, Pageable pageRequest);
}

乐观锁定

文件库键/值密钥引擎版本 2 可以维护版本控制的密钥。 Spring Vault 支持通过域模型中的 version 属性进行版本控制,该属性带有@Version. 使用乐观锁定可确保更新仅应用于具有匹配版本的密钥。 因此,version 属性的实际值会通过cas财产。 如果另一个作同时更改了密钥,则会引发 OptimisticLockingFailureException,并且不会更新密钥。spring-doc.cadn.net.cn

版本属性必须是数值属性,例如intlong并映射到cas属性。spring-doc.cadn.net.cn

例 8.示例版本控制实体
@Secret
class VersionedCredentials {

  @Id String id;
  @Version int version;
  String password;
  String socialSecurityNumber;
  Address address;
}

以下示例显示了这些功能:spring-doc.cadn.net.cn

例 9.示例版本控制实体
VersionedCredentialsRepository repo = …;

VersionedCredentials credentials = repo.findById("sample-credentials").get();    (1)

VersionedCredentials concurrent = repo.findById("sample-credentials").get();     (2)

credentials.setPassword("something-else");

repos.save(credentials);                                                         (3)


concurrent.setPassword("concurrent change");

repos.save(concurrent); // throws OptimisticLockingFailureException              (4)
1 通过 Id 获取密钥sample-credentials.
2 按 Id 获取密钥的第二个实例sample-credentials.
3 更新 secret 并让 Vault 递增版本。
4 更新使用以前版本的第二个实例。 作失败,并显示OptimisticLockingFailureException因为在此期间 Vault 中的版本已递增。
删除受版本控制的密钥时,按 ID 删除将删除最新的密钥。Delete by entity (按实体删除) 删除所提供版本的密钥。

访问受版本控制的密钥

键/值版本 2 密钥引擎维护可通过实现RevisionRepository在您的 Vault 存储库接口声明中。 修订版本库定义查找方法以获取特定标识符的修订版本。 标识符必须为String.spring-doc.cadn.net.cn

例 10.实施RevisionRepository
interface RevisionCredentialsRepository extends CrudRepository<Credentials, String>,
                                        RevisionRepository<Credentials, String, Integer> (1)
{

}
1 第一个类型参数 (Credentials) 表示实体类型,第二个 (String) 表示 id 属性的类型,最后一个 (Integer) 是修订版号的类型。Vault 仅支持Stringidentifiers 和Integer修订号。

用法

您现在可以使用RevisionRepository查询实体的修订版,如下例所示:spring-doc.cadn.net.cn

例 11.用RevisionRepository
RevisionCredentialsRepository repo = …;

Revisions<Integer, Credentials> revisions = repo.findRevisions("my-secret-id");

Page<Revision<Integer, Credentials>> firstPageOfRevisions = repo.findRevisions("my-secret-id", Pageable.ofSize(4));