# 14.5.1 在 Git 中加密属性

除了使用未加密的值外，Config Server 还支持在 Git 存储的配置文件中使用加密值。在 Git 存储中使用加密值的关键，实际上是一个密钥，一个用于加密的密钥。

要启用对属性加密，需要使用加密密钥。在将值传到客户端之前，使用密钥对加密值进行解密。Config Server 支持对称加密和非对称加密。设置对称加密的密钥，可在 Config Server 自身的配置中设置 `encrypt.key` 属性值。这个值可以用作加密和解密：

```yaml
encrypt:
  key: s3cr3t
```

在启动配置（例如 `bootstrap.properties` 或 `bootstrap.yml` 中）中设置此属性非常重要。这样使 Config Server 对外提供服务之前，可以通过自动配置加载此属性。

为了提高安全性，您可以选择使用非对称加密密钥，如 RSA 密钥对或对 keystore 的引用。要创建这样的密钥对，可以使用 keytool 命令行工具：

```bash
$ keytool -genkeypair -alias tacokey -keyalg RSA \
-dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
-keypass s3cr3t -keystore keystore.jks -storepass l3tm31n
```

生成的 keystore 将写入名为 `keystore.jks` 的文件中，可以选择把 keystore 文件保存在文件系统上，或将其放置在应用程序本身中。无论哪种情况，您都需要在 Config Server 的 `bootstrap.yml` 文件中，指定 keystore 文件的位置以及授权信息。

> 注意：要在 Config Server 中使用加密功能，必须安装 `Java Cryptography Extensions Unlimited Strength` 策略文件。详细信息请参阅 Oracle 的 Java SE 页：<http://www.oracle.com/technetwork/java/javase/downloads/index.html>。

假设您选择将 keystore 打包到应用程序中，并放在类路径的根目录。然后就可以通过配置 Config Server 的以下属性使用 keystore：

```yaml
encrypt:
  key-store:
    alias: tacokey
    location: classpath:/keystore.jks
    password: l3tm31n
    secret: s3cr3t
```

有了密钥或 keystore，您现在需要一些加密的数据。Config Server 提供了 `/encrypt` 加密接口。所要做的就是通过 POST 请求，把一些要加密的数据发送到 `/encrypt` 接口。例如，假设您要加密 MongoDB 数据库的密码。使用 curl 可以这样加密这个密码：

```bash
$ curl localhost:8888/encrypt -d "s3cr3tP455w0rd"
93912a660a7f3c04e811b5df9a3cf6e1f63850cdcd4aa092cf5a3f7e1662fab7
```

提交 POST 请求后，您将收到一个加密值作为响应。剩下的就是复制该值，并将其粘贴到在 Git 存储库中保存的配置文件中。

要设置 MongoDB 密码，请在 `application.yml` 中添加 `spring.data.mongodb.password` 属性：

```yaml
spring:
  data:
    mongodb:
      password: '{cipher}93912a660a7f3c04e811b5df9a3cf6e1f63850...'
```

请注意，给 `spring.data.mongodb.password` 设置的值是用单引号(`'`)引起来的，前缀为 `{cipher}`。这会让 Config Server 识别到，这是一个加密值，而不是普通的未加密值。

对 `application.yml` 的修改提交并推送到到 Git 存储库以后，Config Server 就准备好了提供加密属性服务。要查看它的运行情况，可使用 curl 模拟客户端调用：

```bash
$ curl localhost:8888/application/default | jq
{
  "name": "app",
  "profiles": [
    "prof"
  ],
  "label": null,
  "version": "464adfd43485182e4e0af08c2aaaa64d2f78c4cf",
  "state": null,
  "propertySources": [
    {
      "name": "http://localhost:10080/tacocloud/tacocloudconfig/application.yml",
      "source": {
        "spring.data.mongodb.password": "s3cr3tP455w0rd"
      }
    }
  ]
}
```

如你所见，属性 `spring.data.mongodb.password` 的值是解密的形式。默认情况下，Config Server 提供的任何加密值，在后端 Git 存储库中都是加密的；它们在被使用之前会被解密。这意味着使用 Config Server 的客户端应用程序，不需要任何特殊的代码或配置来接收在 Git 中加密的属性。

如果您希望 Config Server 提供仍然加密的属性，您可以设置 `spring.cloud.config.server.encrypt.enabled` 属性为 false:

```yaml
spring:
  cloud:
    config:
      server:
        git:
          uri: http://localhost:10080/tacocloud/tacocloud-config
        encrypt:
          enabled: false
```

这将导致 Config Server 提供的所有属性值，包括加密属性值，与 Git 存储库中设置的值完全相同。再次使用 curl 命令模拟客户端调用，以显示禁用解密后的效果：

```bash
$ curl localhost:8888/application/default | jq
{
  ...
  "propertySources": [
    {
        "name": "http://localhost:10080/tacocloud/tacocloudconfig/application.yml",
        "source": {
        "spring.data.mongodb.password": "{cipher}AQA4JeVhf2cRXW..."
        }
    }
  ]
}
```

当然，如果客户端接收到加密后的属性值，那么客户端现在就负责自行解密了。

尽管可以将加密的属性存储在 Git 中，再由 Config Server 提供服务。但我们已经看到加密并不是 Git 原生的能力，这需要您做一些工作，以便使用任何写入 Git 存储库的数据。而且，除非您的应用程序自行解密，否则使用 Config Server API 能够让任何人获取解密后的信息。让我们看看另一种配置 Config Server 的选择，它只为那些有权看到他们的使用方提供服务。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://potoyang.gitbook.io/spring-in-action-v5/di-14-zhang-pei-zhi-guan-li/14.5-wei-pei-zhi-de-shu-xing-jia-mi/14.5.1-zai-git-zhong-jia-mi-shu-xing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
