使用 Java 类并映射到 Java 类的响应允许读取、写入和删除等基本数据操作。
Vault 存储库在 Vault 之上应用了 Spring Data 的存储库概念。
Vault 存储库公开了基本的 CRUD 功能,并支持使用约束标识符属性、分页和排序的谓词进行查询派生。
Vault 存储库使用键/值密钥引擎功能来保存和查询数据。
从版本 2.4 开始,Spring Vault 可以使用额外的键/值版本 2 密钥引擎,实际的密钥引擎版本是在运行时发现的。VaultTemplate
在版本控制的键/值机密引擎中删除时,请使用该操作。机密不会通过 .DELETE CrudRepository.delete(…) |
在 Spring Data Commons 参考文档中阅读有关 Spring Data Repositories 的更多信息。 参考文档将向您介绍 Spring Data 存储库。 |
在版本控制的键/值机密引擎中删除时,请使用该操作。机密不会通过 .DELETE CrudRepository.delete(…) |
在 Spring Data Commons 参考文档中阅读有关 Spring Data Repositories 的更多信息。 参考文档将向您介绍 Spring Data 存储库。 |
用法
要访问存储在保险柜中的域实体,您可以利用存储库支持,从而大大简化这些实体的实现。
@Secret
class Credentials {
@Id String id;
String password;
String socialSecurityNumber;
Address address;
}
我们这里有一个非常简单的域对象。
请注意,它有一个名为 annotated with 的属性,并且对其类型有一个注释。
这两个密钥负责创建用于在 Vault 中将对象保存为 JSON 的实际密钥。id
org.springframework.data.annotation.Id
@Secret
用“注释”和“命名”的属性被视为标识符属性。
那些有注释的人比其他人更受青睐。@Id id |
下一步是声明使用域对象的存储库接口。
Credentials
interface CredentialsRepository extends CrudRepository<Credentials, String> {
}
随着存储库的扩展,它提供了基本的 CRUD 和查询方法。
Vault 存储库需要 Spring Data 组件。
确保在类路径中包含 和 项目。CrudRepository
spring-data-commons
spring-data-keyvalue
实现此目的的最简单方法是设置依赖项管理并将项目添加到您的:pom.xml
然后将以下内容添加到依赖项部分。pom.xml
<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.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-keyvalue</artifactId>
<!-- Version inherited from the BOM -->
</dependency>
</dependencies>
我们需要在两者之间将东西粘合在一起的是相应的 Spring 配置。
@Configuration
@EnableVaultRepositories
class ApplicationConfig {
@Bean
VaultTemplate vaultTemplate() {
return new VaultTemplate(…);
}
}
根据上面的设置,我们可以继续注入到我们的组件中。CredentialsRepository
@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 | 使用密钥模式存储 Vault Hash 内部的属性,在本例中为 ,在键值密钥引擎中。Credentials keyspace/id credentials/heisenberg |
2 | 使用提供的 ID 检索存储在 中的对象。keyspace/id |
3 | 计算 on 定义的密钥空间凭据中可用的实体总数。@Secret Credentials |
4 | 从 Vault 中删除给定对象的密钥。 |
用“注释”和“命名”的属性被视为标识符属性。
那些有注释的人比其他人更受青睐。@Id id |
1 | 使用密钥模式存储 Vault Hash 内部的属性,在本例中为 ,在键值密钥引擎中。Credentials keyspace/id credentials/heisenberg |
2 | 使用提供的 ID 检索存储在 中的对象。keyspace/id |
3 | 计算 on 定义的密钥空间凭据中可用的实体总数。@Secret Credentials |
4 | 从 Vault 中删除给定对象的密钥。 |
对象到 Vault JSON 映射
Vault 存储库使用 JSON 作为交换格式将对象存储在 Vault 中。
JSON 和实体之间的对象映射由 完成。
转换器读取和写入包含 正文的 .s 从 Vault 读取,正文由 Jackson 反序列化为 a 和 。
默认实现读取嵌套值和对象,并将它们转换为实体,反之亦然。VaultConverter
SecretDocument
VaultResponse
VaultResponse
Map
String
Object
VaultConverter
Map
List
Map
给定前面部分中的类型,默认映射如下所示:Credentials
{
"_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 | 该属性包含在根级别以及任何嵌套接口或抽象类型上。_class |
2 | 简单属性值按路径映射。 |
3 | 复杂类型的属性映射为嵌套对象。 |
该属性必须映射到 。@Id String |
类型 | 样本 | 映射值 |
---|---|---|
简单类型 |
字符串 firstname = “Walter”; |
“firstname”: “沃尔特” |
复杂类型 |
地址地址 = new Address(“308 Negra Arroyo Lane”); |
“address”: { “street”: “308 Negra Arroyo Lane” } |
简单类型列表 |
List<String> 昵称 = asList(“walt”, “heisenberg”); |
“昵称”: [“沃尔特”, “海森堡”] |
简单类型地图 |
Map<String, Integer> atts = asMap(“age”, 51) |
“atts” : {“年龄” : 51} |
复杂类型列表 |
List<Address> addresses = asList(new Address(“308... |
“address”: [{ “street”: “308 Negra Arroyo Lane” }, ...] |
您可以通过在 中注册 来自定义映射行为。
这些转换器可以负责从/转换为类型,例如,而第一个转换器适合将简单属性转换为其 JSON 表示形式,而最后一个复杂类型则适合转换为其 JSON 表示形式。
第二个选项提供对生成的 .
将对象写入将删除内容并重新创建整个条目,因此未映射的数据将丢失。Converter
VaultCustomConversions
LocalDate
SecretDocument
SecretDocument
Vault
1 | 该属性包含在根级别以及任何嵌套接口或抽象类型上。_class |
2 | 简单属性值按路径映射。 |
3 | 复杂类型的属性映射为嵌套对象。 |
该属性必须映射到 。@Id String |
类型 | 样本 | 映射值 |
---|---|---|
简单类型 |
字符串 firstname = “Walter”; |
“firstname”: “沃尔特” |
复杂类型 |
地址地址 = new Address(“308 Negra Arroyo Lane”); |
“address”: { “street”: “308 Negra Arroyo Lane” } |
简单类型列表 |
List<String> 昵称 = asList(“walt”, “heisenberg”); |
“昵称”: [“沃尔特”, “海森堡”] |
简单类型地图 |
Map<String, Integer> atts = asMap(“age”, 51) |
“atts” : {“年龄” : 51} |
复杂类型列表 |
List<Address> addresses = asList(new Address(“308... |
“address”: [{ “street”: “308 Negra Arroyo Lane” }, ...] |
查询和查询方法
查询方法允许从方法名称自动派生简单查询。 保险柜没有查询引擎,但需要直接访问 HTTP 上下文路径。 Vault 查询方法将 Vault 的 API 可能性转换为查询。 查询方法执行在上下文路径下列出子项,对 Id 应用筛选,选择性地使用 offset/limit 限制 Id 流,并在获取结果后应用排序。
interface CredentialsRepository extends CrudRepository<Credentials, String> {
List<Credentials> findByIdStartsWith(String prefix);
}
Vault 存储库的查询方法仅支持对属性使用谓词的查询。@Id |
以下是保险柜支持的关键字的概述。
关键词 | 样本 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
排序和分页
查询方法通过在内存中选择从 Vault 上下文路径检索到的子列表(偏移量/限制)ID 来支持排序和分页。 排序 has 不限于特定字段,这与查询方法谓词不同。 在 Id 过滤后应用未分页排序,并从 Vault 获取所有生成的机密。 这样,查询方法仅提取也作为结果的一部分返回的结果。
使用分页和排序需要在筛选 ID 之前进行机密提取,这会影响性能。 排序和分页可保证返回相同的结果,即使 Vault 返回的 Id 的自然顺序发生更改。 因此,首先从 Vault 获取所有 ID,然后应用排序,然后进行过滤和偏移/限制。
interface CredentialsRepository extends PagingAndSortingRepository<Credentials, String> {
List<Credentials> findTop10ByIdStartsWithOrderBySocialSecurityNumberDesc(String prefix);
List<Credentials> findByIdStarts(String prefix, Pageable pageRequest);
}
Vault 存储库的查询方法仅支持对属性使用谓词的查询。@Id |
关键词 | 样本 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
乐观锁定
保管库键/值机密引擎版本 2 可以维护版本控制的机密。
Spring Vault 支持通过域模型中用 . 注释的 version 属性进行版本控制。
使用乐观锁定可确保更新仅应用于具有匹配版本的机密。
因此,version 属性的实际值将通过该属性添加到更新请求中。
如果其他操作在此期间更改了密钥,则会引发 OptimisticLockingFailureException,并且不会更新密钥。@Version
cas
更新机密时,版本属性必须是数值属性,例如 or 和 映射到该属性。int
long
cas
@Secret
class VersionedCredentials {
@Id String id;
@Version int version;
String password;
String socialSecurityNumber;
Address address;
}
以下示例显示了这些功能:
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 | 更新密钥并让 Vault 递增版本。 |
4 | 更新使用先前版本的第二个实例。
操作失败,同时在Vault中递增版本。OptimisticLockingFailureException |
删除版本化密钥时,按 Id 删除将删除最新的密钥。按实体删除 删除提供的版本的密钥。 |
1 | 通过其 Id 获取机密。sample-credentials |
2 | 通过其 ID 获取密钥的第二个实例。sample-credentials |
3 | 更新密钥并让 Vault 递增版本。 |
4 | 更新使用先前版本的第二个实例。
操作失败,同时在Vault中递增版本。OptimisticLockingFailureException |
删除版本化密钥时,按 Id 删除将删除最新的密钥。按实体删除 删除提供的版本的密钥。 |
访问版本控制的机密
键/值版本 2 密钥引擎维护可通过在 Vault 存储库接口声明中实现 RevisionRepository
来访问的密钥版本。
修订存储库定义查找方法以获取特定标识符的修订。
标识符必须是 。String
RevisionRepository
interface RevisionCredentialsRepository extends CrudRepository<Credentials, String>,
RevisionRepository<Credentials, String, Integer> (1)
{
}
1 | 第一个类型参数 () 表示实体类型,第二个 () 表示 id 属性的类型,最后一个 () 是修订号的类型。保险柜仅支持标识符和修订号。Credentials String Integer String Integer |
用法
现在,您可以使用 from 的方法查询实体的修订,如以下示例所示:RevisionRepository
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));
1 | 第一个类型参数 () 表示实体类型,第二个 () 表示 id 属性的类型,最后一个 () 是修订号的类型。保险柜仅支持标识符和修订号。Credentials String Integer String Integer |