Spring Cloud Config Server

Spring Cloud Config Server 提供了一个基于 HTTP 资源的 API,用于外部配置(键值对或等效的 YAML 内容)。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

该服务器可通过使用 @EnableConfigServer 注解嵌入到 Spring Boot 应用程序中。spring-doc.cadn.net.cn

因此,以下应用程序是一个配置服务器:spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

ConfigServer.java
@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
  public static void main(String[] args) {
    SpringApplication.run(ConfigServer.class, args);
  }
}

像所有 Spring Boot 应用程序一样,它默认在端口 8080 上运行,但您可以通过多种方式将其切换到更常见的端口 8888。
最简单的方法(同时还会设置一个默认配置仓库)是通过使用 spring.config.name=configserver 启动它(Config Server jar 中包含一个 configserver.yml)。
另一种方法是使用您自己的 application.properties,如下例所示:spring-doc.cadn.net.cn

application.properties
server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo

其中 ${user.home}/config-repo 是一个包含 YAML 和属性文件的 Git 仓库。spring-doc.cadn.net.cn

在 Windows 上,如果文件 URL 是带有驱动器前缀的绝对路径(例如 file:///${user.home}/config-repo),则需要额外添加一个斜杠(/)。

以下列表展示了在前面示例中创建 git 仓库的步骤:spring-doc.cadn.net.cn

$ cd $HOME
$ mkdir config-repo
$ cd config-repo
$ git init .
$ echo info.foo: bar > application.properties
$ git add -A .
$ git commit -m "Add application.properties"
使用本地文件系统作为您的 Git 仓库仅适用于测试目的。在生产环境中,您应使用服务器来托管配置仓库。
如果您的配置仓库中仅包含文本文件,初始克隆过程将快速高效。如果您存储了二进制文件,尤其是大型二进制文件,可能会在首次请求配置时遇到延迟,或导致服务器内存溢出错误。

环境存储库

配置服务器的配置数据应存储在何处?
决定此行为的策略是 EnvironmentRepository,用于提供 Environment 对象。
Environment 是来自 Spring Environment(以 propertySources 为主功能)领域的一个浅层副本。
Environment 资源由三个变量参数化:spring-doc.cadn.net.cn

存储库实现通常表现得像一个 Spring Boot 应用程序,从 spring.config.name 加载配置文件(其值等于 {application} 参数),并从 spring.profiles.active 加载配置文件(其值等于 {profiles} 参数)。
配置文件的优先级规则也与常规 Spring Boot 应用程序相同:激活的配置文件优先于默认配置文件;若存在多个配置文件,则最后一个生效(类似于向 Map 中添加条目)。spring-doc.cadn.net.cn

以下示例客户端应用程序具有此引导配置:spring-doc.cadn.net.cn

spring:
  application:
    name: foo
  profiles:
    active: dev,mysql

(与 Spring Boot 应用程序一样,这些属性也可以通过环境变量或命令行参数进行设置)。spring-doc.cadn.net.cn

如果存储库是基于文件的,服务器会从 Environment(在所有客户端之间共享)和 foo.yml(其中 foo.yml 具有更高优先级)创建一个 application.yml。如果 YAML 文件内部包含指向 Spring 配置文件的文档,则这些配置文件将按列出的配置文件顺序以更高优先级应用。如果存在特定于配置文件的 YAML(或属性)文件,它们也将以高于默认值的优先级应用。更高的优先级意味着在 Environment 中更早列出 PropertySource。这些规则同样适用于独立的 Spring Boot 应用程序。)spring-doc.cadn.net.cn

您可以将 spring.cloud.config.server.accept-empty 设置为 false,这样当应用程序未找到时,服务器将返回 HTTP 404 状态码。默认情况下,此标志设置为 true。spring-doc.cadn.net.cn

Git 后端

默认的 EnvironmentRepository 实现使用 Git 后端,这在管理升级和物理环境以及审计变更方面非常便捷。要更改存储库的位置,您可以在配置服务器(例如在 application.yml 中)设置 spring.cloud.config.server.git.uri 配置属性。如果您使用 file: 前缀进行设置,它应能从本地仓库中正常工作,从而让您无需服务器即可快速轻松地开始开发。然而,在这种情况下,服务器直接在本地仓库上操作,而无需对其进行克隆(是否为裸仓库并不重要,因为配置服务器永远不会对“远程”仓库进行任何更改)。为了扩展配置服务器并使其具备高可用性,您需要确保所有服务器实例都指向同一个仓库,因此只有共享文件系统才能满足要求。即使在这种情况下,也建议为共享文件系统仓库使用 ssh: 协议,以便服务器可以对其进行克隆,并将本地工作副本用作缓存。spring-doc.cadn.net.cn

此存储库实现将 HTTP 资源的 {label} 参数映射到 Git 标签(提交 ID、分支名称或标签)。
如果 Git 分支或标签名称中包含斜杠(/),则 HTTP URL 中的标签应改用特殊字符串 (_) 指定(以避免与其他 URL 路径产生歧义)。
例如,若标签为 foo/bar,替换斜杠后得到的标签为:foo(_)bar
特殊字符串 (_) 也可应用于 {application} 参数。
如果您使用命令行客户端(如 curl),请注意 URL 中的括号——您应使用单引号(' ')将其从 shell 中转义。spring-doc.cadn.net.cn

跳过SSL证书验证

配置服务器对 Git 服务器 SSL 证书的验证可以通过将 git.skipSslValidation 属性设置为 true(默认值为 false)来禁用。spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://example.com/my/repo
          skipSslValidation: true
设置 HTTP 连接超时

您可以配置配置服务器等待获取 HTTP 连接的时间(单位:秒)。使用 git.timeout 属性。spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://example.com/my/repo
          timeout: 4
Git URI 中的占位符

Spring Cloud Config Server 支持带有占位符的 Git 仓库 URL,用于 {application}{profile}(如果需要的话还可包括 {label}),但请注意,标签最终仍会以 Git 标签的形式应用。因此,您可以通过采用类似以下的结构,来支持“每个应用一个仓库”的策略。spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/myorg/{application}

您还可以通过使用类似的模式但配合{profile}来支持‘每个配置文件一个仓库’的策略。spring-doc.cadn.net.cn

此外,在您的 {application} 参数中使用特殊字符串 "(_}" 可以启用对多个组织的支持,如下例所示:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/{application}

其中 {application} 是在请求时以以下格式提供的: organization(_)applicationspring-doc.cadn.net.cn

模式匹配与多个仓库

Spring Cloud Config 还包括对更复杂需求的支持,支持根据应用程序名称和配置文件名称进行模式匹配。模式格式为以逗号分隔的 {application}/{profile} 个名称列表,其中包含通配符(注意:以通配符开头的模式可能需要加引号),如下例所示:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            simple: https://github.com/simple/config-repo
            special:
              pattern: special*/dev*,*special*/dev*
              uri: https://github.com/special/config-repo
            local:
              pattern: local*
              uri: file:/home/configsvc/config-repo

如果 {application}/{profile} 与任何模式都不匹配,则使用 spring.cloud.config.server.git.uri 下定义的默认 URI。在上述示例中,对于“simple”存储库,模式为 simple/*(它仅匹配所有配置文件中名为 simple 的一个应用)。而“local”存储库则匹配所有以 local 开头的应用名称(在任何不包含配置文件匹配器的模式末尾,系统会自动添加 /* 后缀)。spring-doc.cadn.net.cn

在“简单”示例中使用的“一行式”快捷方式仅当需要设置的唯一属性是 URI 时才可使用。如果需要设置其他内容(如凭据、模式等),则必须使用完整形式。

仓库中的 pattern 属性实际上是一个数组,因此您可以使用 YAML 数组(或属性文件中的 [0][1] 等后缀)来绑定多个模式。如果要运行具有多个配置文件的应用程序,您可能需要这样做,如下例所示:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            development:
              pattern:
                - '*/development'
                - '*/staging'
              uri: https://github.com/development/config-repo
            staging:
              pattern:
                - '*/qa'
                - '*/production'
              uri: https://github.com/staging/config-repo
Spring Cloud 会推断,若模式中包含一个不以 * 结尾的配置文件,则实际意图是匹配以该模式开头的一组配置文件(例如,*/staging["*/staging", "*/staging,*"] 的快捷方式,依此类推)。

spring-doc.cadn.net.cn

这种情况很常见,例如,您需要在本地以 “development” 配置文件运行应用程序,同时又需在远程以 “cloud” 配置文件运行。spring-doc.cadn.net.cn

每个存储库还可以可选地在子目录中存储配置文件,并且可以指定搜索这些目录的模式,如 search-paths 所示。以下示例显示了位于顶层的配置文件:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          search-paths:
            - foo
            - bar*

在前面的示例中,服务器会在顶层目录以及 foo/ 子目录中查找配置文件,并且还会查找任何以 bar 开头的子目录。spring-doc.cadn.net.cn

默认情况下,服务器在首次请求配置时会克隆远程仓库。服务器可配置为在启动时克隆这些仓库,如下所示的顶级示例:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://git/common/config-repo.git
          repos:
            team-a:
                pattern: team-a-*
                cloneOnStart: true
                uri: https://git/team-a/config-repo.git
            team-b:
                pattern: team-b-*
                cloneOnStart: false
                uri: https://git/team-b/config-repo.git
            team-c:
                pattern: team-c-*
                uri: https://git/team-a/config-repo.git

在前面的例子中,服务器在启动时克隆 team-a 的 config-repo,然后才开始接受任何请求。所有其他仓库直到从该仓库请求配置后才会被克隆。spring-doc.cadn.net.cn

在配置服务器启动时,将存储库设置为要克隆的仓库,有助于在配置服务器启动过程中快速识别配置源的错误配置(例如无效的仓库 URI),而无需等待应用程序从该配置源请求配置。

spring-doc.cadn.net.cn

当某个配置源未启用 cloneOnStart 时,配置服务器可能成功启动,但其使用了错误或无效的配置源;此时系统不会立即检测到错误,直到有应用程序向该配置源请求配置信息时才会发现问题。spring-doc.cadn.net.cn

身份验证

要对远程仓库使用 HTTP 基本认证,请分别添加 usernamepassword 属性(而非在 URL 中),如下例所示:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          username: trolley
          password: strongpassword

如果您不使用 HTTPS 且不使用用户凭据,当将密钥存储在默认目录(~/.ssh)中且 URI 指向 SSH 地址(如 [email protected]:configuration/cloud-configuration)时,SSH 应该可以开箱即用。重要的是,Git 服务器的条目必须存在于 ~/.ssh/known_hosts 文件中,并且其格式应为 ssh-rsa。其他格式(例如 ecdsa-sha2-nistp256)不被支持。为避免意外情况,您应确保 known_hosts 文件中仅存在一条针对 Git 服务器的条目,且该条目与您提供给配置服务器的 URL 相匹配。如果在 URL 中使用了主机名,则您希望在 known_hosts 文件中精确包含该主机名(而非 IP 地址)。仓库通过 JGit 进行访问,因此您在 JGit 上找到的任何文档均适用。HTTPS 代理设置可在 ~/.git/config 中设置,或(如同其他任何 JVM 进程一样)通过系统属性(-Dhttps.proxyHost-Dhttps.proxyPort)进行设置。spring-doc.cadn.net.cn

如果您不知道您的 ~/.git 目录位于何处,可使用 git config --global 来修改设置(例如,git config --global http.sslVerify false)。

JGit 要求 RSA 密钥使用 PEM 格式。下面是一个来自 OpenSSH 的 ssh-keygen 示例命令,该命令可生成符合要求的密钥格式:spring-doc.cadn.net.cn

ssh-keygen -m PEM -t rsa -b 4096 -f ~/config_server_deploy_key.rsa

警告:在使用 SSH 密钥时,预期的 SSH 私钥必须以 -----BEGIN RSA PRIVATE KEY----- 开头。如果密钥以 -----BEGIN OPENSSH PRIVATE KEY----- 开头,则当 Spring Cloud Config 服务器启动时,RSA 密钥将无法加载。该错误的提示如下:spring-doc.cadn.net.cn

- Error in object 'spring.cloud.config.server.git': codes [PrivateKeyIsValid.spring.cloud.config.server.git,PrivateKeyIsValid]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.cloud.config.server.git.,]; arguments []; default message []]; default message [Property 'spring.cloud.config.server.git.privateKey' is not a valid private key]

为纠正上述错误,必须将 RSA 密钥转换为 PEM 格式。上面提供了一个使用 OpenSSH 的示例,用于生成符合要求格式的新密钥。spring-doc.cadn.net.cn

与 AWS CodeCommit 的身份验证

Spring Cloud Config Server 还支持 AWS CodeCommit 身份验证。
AWS CodeCommit 在使用 Git 命令行时会使用一个身份验证辅助工具。
但该辅助工具不适用于 JGit 库,因此当 Git URI 匹配 AWS CodeCommit 的模式时,会为 AWS CodeCommit 创建一个 JGit 凭据提供程序(CredentialProvider)。
AWS CodeCommit 的 URI 遵循以下模式:spring-doc.cadn.net.cn

https//git-codecommit.${AWS_REGION}.amazonaws.com/v1/repos/${repo}.

如果您为 AWS CodeCommit URI 提供用户名和密码,它们必须是提供对存储库访问权限的 AWS 访问密钥 ID 和秘密访问密钥
如果您未指定用户名和密码,则会通过使用 AWS 默认凭证提供程序链 来检索访问密钥 ID 和秘密访问密钥。spring-doc.cadn.net.cn

如果您的 Git URI 与 CodeCommit URI 模式(如前所示)匹配,则必须在用户名和密码中提供有效的 AWS 凭据,或在默认凭据提供程序链所支持的任一位置中提供。
AWS EC2 实例可使用 EC2 实例的 IAM 角色spring-doc.cadn.net.cn

aws-java-sdk-core jar 是一个可选依赖项。

spring-doc.cadn.net.cn

如果 aws-java-sdk-core jar 不在您的类路径中,则无论 Git 服务器 URI 为何,AWS Code Commit 凭据提供程序均不会被创建。spring-doc.cadn.net.cn

与 Google Cloud Source 的身份验证

Spring Cloud Config Server 还支持对 Google Cloud Source 仓库进行身份验证。spring-doc.cadn.net.cn

如果您的 Git URI 使用 httphttps 协议,且域名是 source.developers.google.com,则将使用 Google Cloud Source 凭据提供程序。Google Cloud Source 仓库 URI 的格式为 https://source.developers.google.com/p/${GCP_PROJECT}/r/${REPO}。要获取您仓库的 URI,请在 Google Cloud Source 界面中点击“克隆”,然后选择“手动生成凭据”。请勿生成任何凭据,只需复制显示的 URI 即可。spring-doc.cadn.net.cn

Google Cloud Source 凭据提供程序将使用 Google Cloud Platform 应用默认凭据。有关如何为系统创建应用默认凭据的详细信息,请参阅 Google Cloud SDK 文档。此方法在开发环境中适用于用户账户,在生产环境中适用于服务账户。spring-doc.cadn.net.cn

com.google.auth:google-auth-library-oauth2-http 是一个可选依赖项。如果 google-auth-library-oauth2-http jar 包不在您的类路径中,则无论 Git 服务器 URI 为何,都不会创建 Google Cloud Source 凭据提供者。
Git SSH 配置使用属性

默认情况下,Spring Cloud Config Server 所使用的 JGit 库在通过 SSH URI 连接 Git 仓库时,会使用 SSH 配置文件(如 ~/.ssh/known_hosts/etc/ssh/ssh_config)。spring-doc.cadn.net.cn

  spring:
    cloud:
      config:
        server:
          git:
            uri: [email protected]:team/repo1.git
            ignoreLocalSshSettings: true
            hostKey: someHostKey
            hostKeyAlgorithm: ssh-rsa
            privateKey: |
                         -----BEGIN RSA PRIVATE KEY-----
                         MIIEpgIBAAKCAQEAx4UbaDzY5xjW6hc9jwN0mX33XpTDVW9WqHp5AKaRbtAC3DqX
                         IXFMPgw3K45jxRb93f8tv9vL3rD9CUG1Gv4FM+o7ds7FRES5RTjv2RT/JVNJCoqF
                         ol8+ngLqRZCyBtQN7zYByWMRirPGoDUqdPYrj2yq+ObBBNhg5N+hOwKjjpzdj2Ud
                         1l7R+wxIqmJo1IYyy16xS8WsjyQuyC0lL456qkd5BDZ0Ag8j2X9H9D5220Ln7s9i
                         oezTipXipS7p7Jekf3Ywx6abJwOmB0rX79dV4qiNcGgzATnG1PkXxqt76VhcGa0W
                         DDVHEEYGbSQ6hIGSh0I7BQun0aLRZojfE3gqHQIDAQABAoIBAQCZmGrk8BK6tXCd
                         fY6yTiKxFzwb38IQP0ojIUWNrq0+9Xt+NsypviLHkXfXXCKKU4zUHeIGVRq5MN9b
                         BO56/RrcQHHOoJdUWuOV2qMqJvPUtC0CpGkD+valhfD75MxoXU7s3FK7yjxy3rsG
                         EmfA6tHV8/4a5umo5TqSd2YTm5B19AhRqiuUVI1wTB41DjULUGiMYrnYrhzQlVvj
                         5MjnKTlYu3V8PoYDfv1GmxPPh6vlpafXEeEYN8VB97e5x3DGHjZ5UrurAmTLTdO8
                         +AahyoKsIY612TkkQthJlt7FJAwnCGMgY6podzzvzICLFmmTXYiZ/28I4BX/mOSe
                         pZVnfRixAoGBAO6Uiwt40/PKs53mCEWngslSCsh9oGAaLTf/XdvMns5VmuyyAyKG
                         ti8Ol5wqBMi4GIUzjbgUvSUt+IowIrG3f5tN85wpjQ1UGVcpTnl5Qo9xaS1PFScQ
                         xrtWZ9eNj2TsIAMp/svJsyGG3OibxfnuAIpSXNQiJPwRlW3irzpGgVx/AoGBANYW
                         dnhshUcEHMJi3aXwR12OTDnaLoanVGLwLnkqLSYUZA7ZegpKq90UAuBdcEfgdpyi
                         PhKpeaeIiAaNnFo8m9aoTKr+7I6/uMTlwrVnfrsVTZv3orxjwQV20YIBCVRKD1uX
                         VhE0ozPZxwwKSPAFocpyWpGHGreGF1AIYBE9UBtjAoGBAI8bfPgJpyFyMiGBjO6z
                         FwlJc/xlFqDusrcHL7abW5qq0L4v3R+FrJw3ZYufzLTVcKfdj6GelwJJO+8wBm+R
                         gTKYJItEhT48duLIfTDyIpHGVm9+I1MGhh5zKuCqIhxIYr9jHloBB7kRm0rPvYY4
                         VAykcNgyDvtAVODP+4m6JvhjAoGBALbtTqErKN47V0+JJpapLnF0KxGrqeGIjIRV
                         cYA6V4WYGr7NeIfesecfOC356PyhgPfpcVyEztwlvwTKb3RzIT1TZN8fH4YBr6Ee
                         KTbTjefRFhVUjQqnucAvfGi29f+9oE3Ei9f7wA+H35ocF6JvTYUsHNMIO/3gZ38N
                         CPjyCMa9AoGBAMhsITNe3QcbsXAbdUR00dDsIFVROzyFJ2m40i4KCRM35bC/BIBs
                         q0TY3we+ERB40U8Z2BvU61QuwaunJ2+uGadHo58VSVdggqAo0BSkH58innKKt96J
                         69pcVH/4rmLbXdcmNYGm6iu+MlPQk4BUZknHSmVHIFdJ0EPupVaQ8RHT
                         -----END RSA PRIVATE KEY-----

以下表格描述了 SSH 配置属性。spring-doc.cadn.net.cn

<p>表 1. SSH 配置属性</p>
属性名称 备注

忽略本地SSH设置spring-doc.cadn.net.cn

如果 true,则使用基于属性的配置而非基于文件的 SSH 配置。必须设置为 spring.cloud.config.server.git.ignoreLocalSshSettings不能在仓库定义内部设置。spring-doc.cadn.net.cn

privateKeyspring-doc.cadn.net.cn

有效的 SSH 私钥。如果 ignoreLocalSshSettings 为 true 且 Git URI 格式为 SSH,则必须设置。spring-doc.cadn.net.cn

hostKeyspring-doc.cadn.net.cn

有效的 SSH 主机密钥。如果也设置了 hostKeyAlgorithm,则必须设置。spring-doc.cadn.net.cn

hostKeyAlgorithmspring-doc.cadn.net.cn

其中一个 ssh-dss, ssh-rsa, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, or ecdsa-sha2-nistp521。如果也设置了 hostKey,则必须设置。spring-doc.cadn.net.cn

strictHostKeyCheckingspring-doc.cadn.net.cn

truefalse。如果为 false,则忽略主机密钥相关的错误。spring-doc.cadn.net.cn

knownHostsFilespring-doc.cadn.net.cn

自定义 .known_hosts 文件的位置。spring-doc.cadn.net.cn

首选认证方式spring-doc.cadn.net.cn

重写服务器身份验证方法的顺序。这应允许在服务器在 publickey 方法之前执行键盘交互式身份验证时绕过登录提示。spring-doc.cadn.net.cn

Git 搜索路径中的占位符

Spring Cloud Config Server 还支持包含占位符的搜索路径,用于 {application}{profile}(如果您需要,还可使用 {label}),如下例所示:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          search-paths: '{application}'

前面的清单会导致在存储库中搜索与目录同名的文件(以及顶层目录)。通配符在搜索路径中也有效,并支持占位符(任何匹配的目录都将包含在搜索中)。spring-doc.cadn.net.cn

强制拉取 Git 仓库

如前所述,Spring Cloud Config Server 会在本地副本变得“脏”(例如,由操作系统进程更改文件夹内容)时,克隆远程 Git 仓库,以确保 Spring Cloud Config Server 能够从远程仓库更新本地副本。spring-doc.cadn.net.cn

为了解决此问题,有一个 force-pull 属性,可使 Spring Cloud Config Server 在本地副本已脏时强制从远程仓库拉取,如下例所示:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          force-pull: true

如果您配置了多个仓库(multiple-repositories),可以为每个仓库单独配置 force-pull 属性,如以下示例所示:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://git/common/config-repo.git
          force-pull: true
          repos:
            team-a:
                pattern: team-a-*
                uri: https://git/team-a/config-repo.git
                force-pull: true
            team-b:
                pattern: team-b-*
                uri: https://git/team-b/config-repo.git
                force-pull: true
            team-c:
                pattern: team-c-*
                uri: https://git/team-a/config-repo.git
属性 force-pull 的默认值为 false
删除 Git 仓库中的未跟踪分支

由于 Spring Cloud Config Server 在检出分支到本地仓库(例如通过标签获取属性)后,会克隆远程 Git 仓库的副本,因此它将永远保留该分支,或直到下一次服务器重启(此时会创建新的本地仓库)。因此,可能存在这样一种情况:远程分支已被删除,但其本地副本仍可用于获取数据。如果 Spring Cloud Config Server 客户端服务以 --spring.cloud.config.label=deletedRemoteBranch,master 启动,它将从 deletedRemoteBranch 的本地分支中获取属性,而非从 master 中获取。spring-doc.cadn.net.cn

为了保持本地仓库分支的整洁并同步远程仓库,可设置 deleteUntrackedBranches 属性。这将使 Spring Cloud Config Server 强制 删除本地仓库中未跟踪的分支。
示例:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          deleteUntrackedBranches: true
属性 deleteUntrackedBranches 的默认值为 false
Git 刷新速率

您可以使用 spring.cloud.config.server.git.refreshRate 控制配置服务器从 Git 后端获取更新配置数据的频率。该属性的值以秒为单位指定。默认值为 0,表示配置服务器在每次被请求时都会从 Git 仓库中获取最新的配置。spring-doc.cadn.net.cn

版本控制后端文件系统使用

使用基于 VCS 的后端(git、svn)时,文件会被检出或克隆到本地文件系统。默认情况下,它们会被放置在系统临时目录中,前缀为 config-repo-。例如,在 Linux 上,可能为 /tmp/config-repo-<randomid>。某些操作系统 会定期清理 临时目录。这可能导致意外行为,例如属性缺失。为避免此问题,请通过设置 spring.cloud.config.server.git.basedirspring.cloud.config.server.svn.basedir 更改 Config Server 所使用的目录,使其不位于系统临时目录结构中。

文件系统后端

配置服务器中还存在一个“原生”配置文件(native profile),该配置文件不使用 Git,而是从本地类路径或文件系统加载配置文件(您可使用任意静态 URL 指向所需位置,如 spring.cloud.config.server.native.searchLocations)。
要使用原生配置文件,请通过 spring.profiles.active=native 启动配置服务器。spring-doc.cadn.net.cn

请记住,对于文件资源,请使用 file: 前缀(不带前缀时的默认值通常是类路径)。
与任何 Spring Boot 配置一样,您都可以嵌入 ${} 样式的环境占位符,但请注意,在 Windows 中,绝对路径需要额外的 /(例如,file:///${user.home}/config-repo)。
默认值 searchLocations 与本地 Spring Boot 应用程序相同(即 [classpath:/, classpath:/config, file:./, file:./config])。
这不会将服务器的 application.properties 暴露给所有客户端,因为服务器中存在的任何属性源在发送到客户端之前都会被移除。
文件系统后端非常适合快速入门和测试。</p><p>要在生产环境中使用它,您需要确保文件系统可靠,并且在所有配置服务器实例之间共享。

搜索位置可以包含 {application}{profile}{label} 的占位符。通过这种方式,您可以将路径中的目录进行分离,并选择一种适合您的策略(例如按应用程序或按配置文件设置子目录)。spring-doc.cadn.net.cn

如果您在搜索位置中不使用占位符,此仓库还会将 HTTP 资源的 {label} 参数附加到搜索路径的末尾,因此属性文件会从每个搜索位置(以及一个与标签同名的子目录)中加载,其中带标签的属性在 Spring 环境中具有更高优先级。因此,无占位符时的默认行为与添加一个以 /{label}/ 结尾的搜索位置相同。例如,file:/tmp/configfile:/tmp/config,file:/tmp/config/{label} 的效果相同。您可以通过设置 spring.cloud.config.server.native.addLabelLocations=false 来禁用此行为。spring-doc.cadn.net.cn

Vault 后端

Spring Cloud Config Server 还支持 Vault 作为后端。spring-doc.cadn.net.cn

Vault 是一个用于安全访问密钥的工具。</p><p>密钥是指您希望严格控制访问权限的任何内容,例如 API 密钥、密码、证书及其他敏感信息。Vault 为各类密钥提供统一的访问接口,同时确保严格的访问控制并记录详尽的审计日志。spring-doc.cadn.net.cn

有关 Vault 的更多信息,请参阅 Vault 快速入门指南spring-doc.cadn.net.cn

要启用配置服务器使用 Vault 后端,您可以使用 vault 配置文件运行您的配置服务器。例如,在您的配置服务器的 application.properties 中,您可以添加 spring.profiles.active=vaultspring-doc.cadn.net.cn

默认情况下,配置服务器假定您的 Vault 服务器运行在 http://127.0.0.1:8200。它还假定后端的名称为 secret,密钥为 application。所有这些默认值均可在您的配置服务器的 application.properties 中进行配置。下表描述了可配置的 Vault 属性:spring-doc.cadn.net.cn

姓名 默认值

主机spring-doc.cadn.net.cn

127.0.0.1spring-doc.cadn.net.cn

端口spring-doc.cadn.net.cn

8200spring-doc.cadn.net.cn

方案spring-doc.cadn.net.cn

HTTPspring-doc.cadn.net.cn

后端spring-doc.cadn.net.cn

密钥spring-doc.cadn.net.cn

defaultKeyspring-doc.cadn.net.cn

应用程序spring-doc.cadn.net.cn

个人资料分隔符spring-doc.cadn.net.cn

,spring-doc.cadn.net.cn

kvVersionspring-doc.cadn.net.cn

1spring-doc.cadn.net.cn

跳过SSL验证spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

timeoutspring-doc.cadn.net.cn

5spring-doc.cadn.net.cn

命名空间spring-doc.cadn.net.cn

nullspring-doc.cadn.net.cn

前面表格中的所有属性都必须以 spring.cloud.config.server.vault 为前缀,或放置在复合配置的正确 Vault 部分中。

所有可配置的属性均可在 org.springframework.cloud.config.server.environment.VaultEnvironmentProperties 中找到。spring-doc.cadn.net.cn

Vault 0.10.0 引入了带版本控制的键值后端(k/v 后端版本 2),其暴露的 API 与早期版本不同,现在要求在挂载路径和实际上下文路径之间添加一个 data/,并将密钥封装在 data 对象中。设置 spring.cloud.config.server.vault.kv-version=2 将考虑此变化。

可选地,支持 Vault 企业版 X-Vault-Namespace 请求头。若要将该请求头发送至 Vault,请设置 namespace 属性。spring-doc.cadn.net.cn

在您的配置服务器运行后,您可以向该服务器发送 HTTP 请求,以从 Vault 后端检索值。要执行此操作,您需要一个用于 Vault 服务器的Tokens。spring-doc.cadn.net.cn

首先,将一些数据存入您的 Vault 中,如以下示例所示:spring-doc.cadn.net.cn

$ vault kv put secret/application foo=bar baz=bam
$ vault kv put secret/myapp foo=myappsbar

第二,向您的配置服务器发起 HTTP 请求以检索值,如下例所示:spring-doc.cadn.net.cn

$ curl -X "GET" "http://localhost:8888/myapp/default" -H "X-Config-Token: yourtoken"spring-doc.cadn.net.cn

您应该会看到类似以下的响应:spring-doc.cadn.net.cn

{
   "name":"myapp",
   "profiles":[
      "default"
   ],
   "label":null,
   "version":null,
   "state":null,
   "propertySources":[
      {
         "name":"vault:myapp",
         "source":{
            "foo":"myappsbar"
         }
      },
      {
         "name":"vault:application",
         "source":{
            "baz":"bam",
            "foo":"bar"
         }
      }
   ]
}

客户端向 Config Server 提供必要认证信息,以使 Config Server 能够与 Vault 进行通信的默认方式是设置 X-Config-Token 请求头。然而,您也可以选择不设置该请求头,并在服务器端进行认证配置,方法是使用与 Spring Cloud Vault 相同的配置属性。需要设置的属性是 spring.cloud.config.server.vault.authentication。该属性应设置为所支持的认证方式之一。根据所使用的认证方式,您可能还需要设置其他特定于该认证方式的属性,此时可使用与 spring.cloud.vault 文档中所述相同的属性名称,但前缀改为 spring.cloud.config.server.vault。更多详情请参见 Spring Cloud Vault 参考指南spring-doc.cadn.net.cn

如果省略 X-Config-Token 请求头,并使用服务器属性来设置认证,则 Config Server 应用需要额外依赖 Spring Vault,以启用其他认证选项。有关如何添加该依赖的详细信息,请参阅 Spring Vault 参考指南
多个属性源

在使用 Vault 时,您可以为您的应用程序提供多个属性源。例如,假设您已将数据写入 Vault 中以下路径:spring-doc.cadn.net.cn

secret/myApp,dev
secret/myApp
secret/application,dev
secret/application

写入 secret/application 的属性对所有使用配置服务器的应用程序均可用。所有使用配置服务器的应用程序。具有名称 myApp 的应用程序将可访问写入 secret/myAppsecret/application 的任何属性。当 myApp 启用了 dev 配置文件时,上述所有路径中写入的属性都将对其可用,其中列表中第一个路径的属性将优先于其他路径的属性。spring-doc.cadn.net.cn

通过代理访问后端

配置服务器可以通过 HTTP 或 HTTPS 代理访问 Git 或 Vault 后端。此行为由 proxy.httpproxy.https 下的设置控制,分别针对 Git 或 Vault。这些设置是按仓库划分的,因此如果您使用的是 复合环境仓库,则必须为复合仓库中的每个后端单独配置代理设置。如果所处网络需要为 HTTP 和 HTTPS URL 分别使用不同的代理服务器,则可为单个后端同时配置 HTTP 和 HTTPS 代理设置。spring-doc.cadn.net.cn

以下表格描述了 HTTP 和 HTTPS 代理的配置属性。所有这些属性都必须以 proxy.httpproxy.https 作为前缀。spring-doc.cadn.net.cn

表2. 代理配置属性
属性名称 备注

主机spring-doc.cadn.net.cn

代理的主机。spring-doc.cadn.net.cn

端口spring-doc.cadn.net.cn

用于访问代理的端口。spring-doc.cadn.net.cn

nonProxyHostsspring-doc.cadn.net.cn

任何配置服务器应通过代理外部访问的主机。如果为 proxy.http.nonProxyHostsproxy.https.nonProxyHosts 都提供了值,则将使用 proxy.http 的值。spring-doc.cadn.net.cn

用户名spring-doc.cadn.net.cn

用于通过代理进行身份验证的用户名。如果同时提供了 proxy.http.usernameproxy.https.username 的值,则将使用 proxy.http 的值。spring-doc.cadn.net.cn

密码spring-doc.cadn.net.cn

用于向代理进行身份验证的密码。如果同时为 proxy.http.passwordproxy.https.password 提供了值,则将使用 proxy.http 的值。spring-doc.cadn.net.cn

以下配置使用 HTTPS 代理访问 Git 仓库。spring-doc.cadn.net.cn

spring:
  profiles:
    active: git
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          proxy:
            https:
              host: my-proxy.host.io
              password: myproxypassword
              port: '3128'
              username: myproxyusername
              nonProxyHosts: example.com

与所有应用程序共享配置

在所有应用程序之间共享配置的方式取决于您采用的方法,具体如下文所述:spring-doc.cadn.net.cn

文件存储库

对于基于文件的(git、svn 和本地)仓库,文件名为 application*application.propertiesapplication.ymlapplication-*.properties 等)的资源会在所有客户端应用之间共享。您可以使用这些文件名的资源来配置全局默认值,并根据需要由特定于应用程序的文件进行覆盖。spring-doc.cadn.net.cn

属性覆盖(property overrides)功能也可用于设置全局默认值,允许各应用通过占位符进行本地覆盖。spring-doc.cadn.net.cn

使用“原生”配置文件(本地文件系统后端)时,应使用显式的搜索位置,该位置不应属于服务器自身的配置。否则,默认搜索位置中的 application* 资源会被移除,因为它们属于服务器本身。
Vault Server

当使用 Vault 作为后端时,您可以通过将配置放在 secret/application 中,与所有应用程序共享配置。例如,如果您运行以下 Vault 命令,则所有使用配置服务器的应用程序都将获得 foobaz 这两个属性:spring-doc.cadn.net.cn

$ vault write secret/application foo=bar baz=bam
可信中心服务器

当使用 CredHub 作为后端时,您可以通过将配置放在 /application/ 中,或为应用程序在 default 配置文件中放置配置,从而与所有应用程序共享配置。例如,如果您运行以下 CredHub 命令,则所有使用配置服务器的应用程序都将能够访问属性 shared.color1shared.color2spring-doc.cadn.net.cn

credhub set --name "/application/profile/master/shared" --type=json
value: {"shared.color1": "blue", "shared.color": "red"}
credhub set --name "/my-app/default/master/more-shared" --type=json
value: {"shared.word1": "hello", "shared.word2": "world"}

JDBC 后端

Spring Cloud Config Server 支持 JDBC(关系型数据库)作为配置属性的后端。您可以通过将 spring-jdbc 添加到类路径并使用 jdbc 配置文件,或通过添加类型为 JdbcEnvironmentRepository 的 Bean 来启用此功能。如果您在类路径中包含了正确的依赖项(有关详细信息,请参阅用户指南),Spring Boot 将自动配置一个数据源。spring-doc.cadn.net.cn

您可以将 JdbcEnvironmentRepository 的自动配置禁用,方法是将 spring.cloud.config.server.jdbc.enabled 属性设置为 falsespring-doc.cadn.net.cn

数据库需要包含一个名为 PROPERTIES 的表,其列名为 APPLICATIONPROFILELABEL(其中通常指代 Environment),此外还需包含 KEYVALUE 用于表示 Properties 样式的键值对。
所有字段在 Java 中均为 String 类型,因此您可以根据需要将其设置为 VARCHAR 的任意长度。
属性值的行为与它们来自名为 {application}-{profile}.properties 的 Spring Boot 属性文件时完全相同,包括所有加密和解密操作,这些操作将作为后处理步骤执行(即不直接在仓库实现中进行)。spring-doc.cadn.net.cn

Redis 后端

Spring Cloud Config Server 支持 Redis 作为配置属性的后端存储。您可以通过添加对 Spring Data Redis 的依赖来启用此功能。spring-doc.cadn.net.cn

pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-redis</artifactId>
	</dependency>
</dependencies>

以下配置使用 Spring Data RedisTemplate 访问 Redis。我们可使用 spring.redis.* 属性来覆盖默认的连接设置。spring-doc.cadn.net.cn

spring:
  profiles:
    active: redis
  redis:
    host: redis
    port: 16379

属性应作为字段存储在哈希表中。哈希表的名称应与 spring.application.name 属性相同,或为 spring.application.namespring.profiles.active[n] 的组合。spring-doc.cadn.net.cn

HMSET sample-app server.port "8100" sample.topic.name "test" test.property1 "property1"

在运行上述命令后,哈希中应包含以下键及其对应的值:spring-doc.cadn.net.cn

HGETALL sample-app
{
  "server.port": "8100",
  "sample.topic.name": "test",
  "test.property1": "property1"
}
当未指定配置文件时,将使用 default

AWS S3 后端

Spring Cloud Config Server 支持 AWS S3 作为配置属性的后端存储。您可以通过添加对 AWS Java SDK for Amazon S3 的依赖来启用此功能。spring-doc.cadn.net.cn

pom.xml
<dependencies>
	<dependency>
		<groupId>com.amazonaws</groupId>
		<artifactId>aws-java-sdk-s3</artifactId>
	</dependency>
</dependencies>

以下配置使用 AWS S3 客户端访问配置文件。我们可使用 spring.awss3.* 属性来选择存储配置文件的存储桶。spring-doc.cadn.net.cn

spring:
  profiles:
    active: awss3
  cloud:
    config:
      server:
        awss3:
          region: us-east-1
          bucket: bucket1

还可以指定一个 AWS URL 来 覆盖您 S3 服务的标准端点,方法是使用 spring.awss3.endpoint。这使得支持 S3 的测试区域以及其他兼容 S3 的存储 API 成为可能。spring-doc.cadn.net.cn

凭据通过 默认 AWS 凭据提供程序链 找到。无需额外配置即可支持带版本和加密的存储桶。spring-doc.cadn.net.cn

配置文件存储在您的存储桶中,文件名为 {application}-{profile}.properties{application}-{profile}.yml{application}-{profile}.json。可选地,您可以提供一个标签来指定文件所在的目录路径。spring-doc.cadn.net.cn

当未指定配置文件时,将使用 default

CredHub 后端

Spring Cloud Config Server 支持 CredHub 作为配置属性的后端。
您可以通过添加对 Spring CredHub 的依赖来启用此功能。spring-doc.cadn.net.cn

pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.credhub</groupId>
		<artifactId>spring-credhub-starter</artifactId>
	</dependency>
</dependencies>

以下配置使用双向 TLS 访问 CredHub:spring-doc.cadn.net.cn

spring:
  profiles:
    active: credhub
  cloud:
    config:
      server:
        credhub:
          url: https://credhub:8844

属性应以 JSON 格式存储,例如:spring-doc.cadn.net.cn

credhub set --name "/demo-app/default/master/toggles" --type=json
value: {"toggle.button": "blue", "toggle.link": "red"}
credhub set --name "/demo-app/default/master/abs" --type=json
value: {"marketing.enabled": true, "external.enabled": false}

所有名称为 spring.cloud.config.name=demo-app 的客户端应用程序都将拥有以下属性:spring-doc.cadn.net.cn

{
    toggle.button: "blue",
    toggle.link: "red",
    marketing.enabled: true,
    external.enabled: false
}
当未指定配置文件时,将使用 default;当未指定标签时,将使用 master 作为默认值。

spring-doc.cadn.net.cn

注意: 添加到 application 中的值将被所有应用程序共享。spring-doc.cadn.net.cn

OAuth 2.0

您可以使用 OAuth 2.0 并以 UAA 作为提供商进行身份验证。spring-doc.cadn.net.cn

pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.security</groupId>
		<artifactId>spring-security-config</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.security</groupId>
		<artifactId>spring-security-oauth2-client</artifactId>
	</dependency>
</dependencies>

以下配置使用 OAuth 2.0 和 UAA 访问 CredHub:spring-doc.cadn.net.cn

spring:
  profiles:
    active: credhub
  cloud:
    config:
      server:
        credhub:
          url: https://credhub:8844
          oauth2:
            registration-id: credhub-client
  security:
    oauth2:
      client:
        registration:
          credhub-client:
            provider: uaa
            client-id: credhub_config_server
            client-secret: asecret
            authorization-grant-type: client_credentials
        provider:
          uaa:
            token-uri: https://uaa:8443/oauth/token
所使用的 UAA 客户端 ID 应具有 credhub.read 作为作用域。

复合环境仓库

在某些场景中,您可能希望从多个环境存储库中提取配置数据。要实现这一点,您可以在配置服务器的应用程序属性文件或 YAML 文件中启用 composite 配置文件。例如,如果您希望从一个 Subversion 存储库以及两个 Git 存储库中提取配置数据,您可以为配置服务器设置以下属性:spring-doc.cadn.net.cn

spring:
  profiles:
    active: composite
  cloud:
    config:
      server:
        composite:
        -
          type: svn
          uri: file:///path/to/svn/repo
        -
          type: git
          uri: file:///path/to/rex/git/repo
        -
          type: git
          uri: file:///path/to/walter/git/repo

使用此配置,优先级由在 composite 键下列出的仓库顺序决定。在上面的例子中,Subversion 仓库首先列出,因此在 Subversion 仓库中找到的值将覆盖在任一 Git 仓库中找到的相同属性的值。在 rex Git 仓库中找到的值将在 walter Git 仓库中找到的相同属性的值之前被使用。spring-doc.cadn.net.cn

如果您只想从每个都是不同类型的存储库中拉取配置数据,可以在配置服务器的应用程序属性或 YAML 文件中启用相应的作用域(profiles),而不是 composite 作用域。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

例如,如果您希望从单个 Git 存储库和单个 HashiCorp Vault 服务器中拉取配置数据,可以为您的配置服务器设置以下属性:spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

spring:
  profiles:
    active: git, vault
  cloud:
    config:
      server:
        git:
          uri: file:///path/to/git/repo
          order: 2
        vault:
          host: 127.0.0.1
          port: 8200
          order: 1

使用此配置,可以通过 order 属性确定优先级。您可以使用 order 属性来为所有存储库指定优先级顺序。该 order 属性的数值越小,其优先级越高。存储库的优先级顺序有助于解决可能存在于多个存储库中且包含相同属性值时的冲突问题。spring-doc.cadn.net.cn

如果您的复合环境包含 Vault 服务器(如上一示例所示),则必须在对配置服务器发出的每个请求中包含一个 Vault Tokens。参见 Vault 后端
从环境仓库中检索值时发生的任何类型故障都会导致整个复合环境失败。

spring-doc.cadn.net.cn

如果您希望即使某个仓库失败,复合环境仍能继续运行,您可以将 spring.cloud.config.server.failOnCompositeError 设置为 falsespring-doc.cadn.net.cn

在使用复合环境时,重要的是所有存储库都包含相同的标签。

spring-doc.cadn.net.cn

如果您拥有与前述示例中类似的环境,并且您请求带有 master 标签的配置数据,但 Subversion 存储库中不存在名为 master 的分支,则整个请求将失败。spring-doc.cadn.net.cn

自定义复合环境仓库

除了使用 Spring Cloud 中的一个环境仓库外,您还可以提供自己的 EnvironmentRepository Bean,将其作为复合环境的一部分包含进来。要实现这一点,您的 Bean 必须实现 EnvironmentRepository 接口。如果您希望控制自定义 EnvironmentRepository 在复合环境中的优先级,还应实现 Ordered 接口,并重写 getOrdered 方法。如果您未实现 Ordered 接口,则您的 EnvironmentRepository 将被赋予最低优先级。spring-doc.cadn.net.cn

属性覆盖

配置服务器具有一个“覆盖”功能,允许操作员为所有应用程序提供配置属性。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

被覆盖的属性无法通过常规 Spring Boot 钩子被应用程序意外修改。spring-doc.cadn.net.cn

要声明覆盖项,请将名称-值对的映射添加到 spring.cloud.config.server.overrides 中,如以下示例所示:spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        overrides:
          foo: bar

前面的示例导致所有配置客户端应用程序均读取 foo=bar,无论其自身配置如何。spring-doc.cadn.net.cn

配置系统无法强制应用程序以任何特定方式使用配置数据。因此,覆盖操作是不可强制执行的。然而,它们确实为 Spring Cloud Config 客户端提供了有用的默认行为。
通常,Spring 环境占位符中带有 ${} 的内容可以通过反斜杠(\)进行转义(并在客户端解析),以转义 ${。例如,\${app.foo:bar} 解析为 bar,除非应用程序提供了其自身的 app.foo
在 YAML 中,您无需转义反斜杠本身。</p><p>然而,在属性文件中,当您在服务器上配置覆盖项时,需要转义反斜杠。

您可以将客户端中所有覆盖项的优先级更改为更接近默认值,从而使应用程序能够通过环境变量或系统属性提供自己的值,方法是在远程仓库中设置 spring.cloud.config.overrideNone=true 标志(默认值为 false)。spring-doc.cadn.net.cn

健康指标

配置服务器附带一个健康指示器,用于检查所配置的 EnvironmentRepository 是否正常工作。默认情况下,它会向 EnvironmentRepository 请求一个名为 app 的应用程序、default 配置文件以及由 EnvironmentRepository 实现提供的默认标签。spring-doc.cadn.net.cn

您可以配置健康指标,以检查更多应用程序,同时结合自定义配置文件和自定义标签,如以下示例所示:spring-doc.cadn.net.cn

spring:
  cloud:
    config:
      server:
        health:
          repositories:
            myservice:
              label: mylabel
            myservice-dev:
              name: myservice
              profiles: development

您可以设置 management.health.config.enabled=false 来禁用健康指标。spring-doc.cadn.net.cn

安全

您可以以任何符合您需求的方式保护您的配置服务器(从物理网络安全到 OAuth2 Tokens),因为 Spring Security 和 Spring Boot 支持多种安全配置。spring-doc.cadn.net.cn

要使用默认的 Spring Boot 配置的 HTTP Basic 安全机制,请将 Spring Security 添加到类路径中(例如,通过 spring-boot-starter-security)。
默认情况下,用户名为 user,密码为随机生成。但在实际应用中,随机密码并不实用,因此我们建议您配置密码(通过设置 spring.security.user.password),并对其进行加密(详见下方关于如何执行此操作的说明)。spring-doc.cadn.net.cn

Actuator and Security

某些平台会配置健康检查或其他类似功能,并指向 /actuator/health 或其他端点。如果配置服务器未将 actuator 作为依赖项,则对 /actuator/ 的请求可能会匹配配置服务器的 API /{application}/{label},从而可能泄露敏感信息。请务必在此情况下添加 spring-boot-starter-actuator 依赖项,并配置用户权限,确保调用 /actuator/ 的用户无权访问配置服务器在 /{application}/{label} 处提供的 API。

加密与解密

要使用加密和解密功能,您需要在 JVM 中安装完整强度的 JCE(它默认不包含在内)。您可从 Oracle 下载“Java 加密扩展 (JCE) 无限制权限策略文件”,并按照安装说明进行操作(本质上,您需要将下载的两个策略文件替换 JRE 的 lib/security 目录中的原有文件)。

如果远程属性源包含加密内容(以 {cipher} 开头的值),则在通过 HTTP 发送给客户端之前会先进行解密。这种配置的主要优势在于,当属性值“处于静止状态”(例如,在 Git 仓库中)时,它们无需以明文形式存在。如果某个值无法解密,则该值将从属性源中移除,并添加一个具有相同键但前缀为 invalid 的额外属性,其值通常为 <n/a>(表示“不适用”)。此举主要是为了防止密文被误用作密码,从而意外泄露。spring-doc.cadn.net.cn

如果您为配置客户端应用程序设置了远程配置仓库,它可能包含一个类似于以下内容的 application.ymlspring-doc.cadn.net.cn

application.yml
spring:
  datasource:
    username: dbuser
    password: '{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ'

文件 application.properties 中的加密值不得用引号包裹。否则,该值将无法解密。以下示例展示了可正常工作的值:spring-doc.cadn.net.cn

application.properties
spring.datasource.username: dbuser
spring.datasource.password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ

您可以安全地将此纯文本推送到共享的 git 仓库,而密钥密码仍会受到保护。spring-doc.cadn.net.cn

服务器还暴露了 /encrypt/decrypt 端点(假设这些端点已受保护,仅由授权代理访问)。
如果您编辑了一个远程配置文件,可以使用配置服务器通过向 /encrypt 端点发送 POST 请求来加密值,如下例所示:spring-doc.cadn.net.cn

$ curl localhost:8888/encrypt -s -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
如果您使用 curl 进行测试,请使用 --data-urlencode(而非 -d),并在要加密的值前加上 =(curl 要求这样做),或显式设置 Content-Type: text/plain,以确保在存在特殊字符(尤其是 '+')时 curl 能正确编码数据。
请确保在加密值中不包含任何 curl 命令的统计信息,这就是为什么示例中使用 -s 选项来静音它们的原因。将值输出到文件有助于避免此问题。

反向操作也可通过 /decrypt(前提是服务器已配置对称密钥或完整密钥对)实现,如下例所示:spring-doc.cadn.net.cn

$ curl localhost:8888/decrypt -s -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret

获取加密后的值,并在将其放入 YAML 或属性文件之前、以及在提交并推送到远程(可能不安全)存储之前,添加 {cipher} 前缀。spring-doc.cadn.net.cn

端点 /encrypt/decrypt 同样接受以 /*/{application}/{profiles} 形式指定的路径,当客户端调用主环境资源时,可用于按应用程序(名称)和配置文件级别分别控制加密。spring-doc.cadn.net.cn

为了以这种细粒度的方式控制加密,您还必须提供一个类型为 TextEncryptorLocator@Bean,该类型可为每个名称和配置文件创建不同的加密器。默认提供的那个则不会这样做(所有加密均使用相同的密钥)。

命令行客户端(已安装 Spring Cloud CLI 扩展)也可以用于加密和解密,如下例所示:spring-doc.cadn.net.cn

$ spring encrypt mysecret --key foo
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
$ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret

要使用文件中的密钥(例如用于加密的 RSA 公共密钥),请在密钥值前加上“@”符号,并提供文件路径,如下例所示:spring-doc.cadn.net.cn

$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...
参数 --key 是必需的(尽管带有 -- 前缀)。

密钥管理

配置服务器可以使用对称(共享)密钥或非对称密钥(RSA 密钥对)。
在安全性方面,非对称选择更优,但通常使用对称密钥更为便捷,因为它只需在 bootstrap.properties 中配置一个属性值即可。spring-doc.cadn.net.cn

要配置对称密钥,您需要将 encrypt.key 设置为一个密钥字符串(或使用 ENCRYPT_KEY 环境变量将其从明文配置文件中移除)。spring-doc.cadn.net.cn

您无法使用 encrypt.key 配置非对称密钥。

要配置非对称密钥,请使用密钥库(例如,由 JDK 自带的 keytool 工具创建的密钥库)。密钥库属性为 encrypt.keyStore.*,其中 * 等于spring-doc.cadn.net.cn

属性 描述

encrypt.keyStore.locationspring-doc.cadn.net.cn

包含一个 Resource 位置spring-doc.cadn.net.cn

encrypt.keyStore.passwordspring-doc.cadn.net.cn

保存用于解锁密钥库的密码spring-doc.cadn.net.cn

encrypt.keyStore.aliasspring-doc.cadn.net.cn

标识在存储中使用哪个键spring-doc.cadn.net.cn

encrypt.keyStore.typespring-doc.cadn.net.cn

要创建的密钥库类型。默认值为 jksspring-doc.cadn.net.cn

加密使用公钥完成,解密则需要私钥。</p><p>因此,原则上,如果您仅希望进行加密(并准备在本地使用私钥自行解密),则只需在服务器上配置公钥即可。</p><p>实际上,您可能并不想在本地进行解密,因为这会将密钥管理流程分散到所有客户端,而非集中于服务器。</p><p>另一方面,如果您的配置服务器相对不安全,且仅有少量客户端需要加密的属性,则此选项可能很有用。spring-doc.cadn.net.cn

为测试创建密钥库

要为测试创建密钥库,您可以使用类似以下的命令:spring-doc.cadn.net.cn

$ keytool -genkeypair -alias mytestkey -keyalg RSA \
  -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
  -keypass changeme -keystore server.jks -storepass letmein
当使用 JDK 11 或更高版本时,使用上述命令时可能会收到以下警告。在此情况下,您可能需要确保 keypassstorepass 的值相匹配。
Warning:  Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified -keypass value.

server.jks 文件放入类路径(例如)中,然后在您的 bootstrap.yml 中,为配置服务器创建以下设置:spring-doc.cadn.net.cn

encrypt:
  keyStore:
    location: classpath:/server.jks
    password: letmein
    alias: mytestkey
    secret: changeme

使用多个密钥和密钥轮换

除了加密属性值中的 {cipher} 前缀外,配置服务器还会在(Base64 编码的)密文开始之前查找零个或多个 {name:value} 前缀。密钥会被传递给一个 TextEncryptorLocator,该组件可根据需要执行任意逻辑以定位用于解密的 TextEncryptor。如果您已配置了密钥库(encrypt.keystore.location),默认的密钥定位器会查找由 key 前缀提供的别名所对应的密钥,其密文格式类似于以下示例:spring-doc.cadn.net.cn

foo:
  bar: `{cipher}{key:testkey}...`

定位器查找名为“testkey”的键。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

也可以通过在前缀中使用 {secret:…​} 值来提供密钥。spring-doc.cadn.net.cn

然而,如果不提供,则默认使用密钥库密码(即在创建密钥库时未指定密钥时所获得的密码)。spring-doc.cadn.net.cn

如果您提供了密钥,还应使用自定义 SecretLocator 对该密钥进行加密。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

当密钥仅用于加密少量配置数据(即,它们未在其他地方使用)时,从密码学角度出发,密钥轮换几乎不需要。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

然而,您可能偶尔需要更改密钥(例如,在发生安全漏洞的情况下)。spring-doc.cadn.net.cn

在这种情况下,所有客户端都需要更改其源配置文件(例如,在 Git 中),并在所有密码中使用新的 {key:…​} 前缀。spring-doc.cadn.net.cn

请注意,客户端需要首先检查密钥别名是否存在于配置服务器的密钥库中。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

如果您希望配置服务器同时处理所有加密和解密操作,也可以将 {name:value} 前缀以纯文本形式发送到 /encrypt 端点。

加密属性服务

有时您希望客户端在本地解密配置,而不是在服务器上进行解密。在这种情况下,如果您提供 encrypt.* 配置来定位密钥,您仍然可以拥有 /encrypt/decrypt 端点,但需要通过在 bootstrap.[yml|properties] 中放置 spring.cloud.config.server.encrypt.enabled=false 显式关闭传出属性的解密功能。如果您不关心端点,那么只要不配置密钥或启用标志,它就应该能正常工作。spring-doc.cadn.net.cn