加密与解密

要使用加密和解密功能,你需要在JVM中安装全强度的JCE(默认不包含)。你可以从Oracle下载“Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files”,并按照安装说明作(基本上你需要将JRE lib/security目录中的两个策略文件替换为你下载的那两个)。这只适用于旧版本的Java。从Java 9开始,最终从Java 8u161开始,默认启用无限强度密码学

如果远程属性源包含加密内容(以 开头的值){密码}),它们在通过HTTP发送给客户端前先被解密。 这种设置的主要优点是,属性值在“静止状态”时不必以纯文本形式存在(例如在 git 仓库中)。 如果某个值无法解密,则从属性源中移除,并添加一个带有相同密钥但前缀为无效以及表示“不适用”的值(通常如此)<无此意>). 这主要是为了防止密文被用作密码并意外泄露。spring-doc.cadn.net.cn

如果你为配置客户端应用设置远程配置仓库,它可能包含application.yml类似于以下内容:spring-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

服务器还会暴露/加密/解密端点(假设这些端点是安全的,只有授权代理才能访问)。 如果你编辑远程配置文件,可以使用配置服务器通过POST到以下内容来加密数值。/加密端点,如下例所示:spring-doc.cadn.net.cn

$ curl localhost:8888/encrypt -s -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
如果你用卷曲测试,那就用--数据-乌伦编码(代替-d)并在加密值前加上(curl要求这样做)或设置显式=内容类型:文本/纯文字以确保在存在特殊字符('+' 特别棘手)时,Curl 正确编码数据。
确保不要在加密值中包含任何 curl 命令的统计数据,这也是示例中使用-s选择让他们闭嘴。将值输入文件可以帮助避免这个问题。

逆作也可以通过以下方式实现/解密(前提是服务器是 配置为对称密钥或全密钥对),如下示例所示:spring-doc.cadn.net.cn

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

取加密值,再加上{密码}在你把它放进 YAML 或 properties 文件之前,以及提交并推送到远程(可能不安全)存储之前,先做前缀。spring-doc.cadn.net.cn

/加密/解密端点也都接受路径,形式为/*/{application}/{profiles}当客户端调用主环境资源时,可以用来按应用程序(名称)和配置文件进行加密控制。spring-doc.cadn.net.cn

要以这种细致的方式控制密码学,你还必须提供@Bean类型TextEncryptorLocator这样每个名字和配置文件都会生成不同的加密器。 默认提供的密钥则不支持(所有加密使用相同的密钥)。

Spring命令行客户端(带有 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+...
--钥匙论元是强制的(尽管有前缀)。--

解密错误

当配置服务器未能解密某个值时,它会生成一个无效HTTP响应中的属性。spring-doc.cadn.net.cn

{
    "label": null,
    "name": "application",
    "profiles": [
        "prd"
    ],
    "propertySources": [
        {
            "name": "file:/demo/configserver/application-prd.yaml",
            "source": {
                "invalid.SharedPassword": "<n/a>"
            }
        },
        {
            "name": "file:/demo/configserver/application.yaml",
            "source": {
                "SharedPassword": "Fill_me_in"
            }
        }
    ],
    "state": null,
    "version": null
}

在上述示例中,配置服务器无法解密 的值共享密码application-prd.yaml所以配置服务器在属性名称前加了无效.spring-doc.cadn.net.cn

如果配置客户端收到了这个响应,然后添加到了应用中环境以及客户端 请求 的值共享密码它会变得Fill_me_in.spring-doc.cadn.net.cn

如果你不想让配置服务器在属性前缀,它就无法解密无效然后你可以设置spring.cloud.config.server.encrypt.prefix-invalid-propertiesfalse.如果你这样做,答案是一样的 配置服务器会长这样:spring-doc.cadn.net.cn

    "label": null,
    "name": "application",
    "profiles": [
        "prd"
    ],
    "propertySources": [
        {
            "name": "file:/demo/configserver/application-prd.yaml",
            "source": {
                "SharedPassword": "AYBKlpcZpaR36OcRDQjNIQl6fmnddAQhetMw/uyTpnn5fDj+unJ9QOEbqiPc9fX0N+CC8i+EJiN6nlH9Xqu6sH1tX/P6zg1CIy+ct/1RWGNbmQ256jc6vQaXhiN8sA8Mr6QiqYnMoBd+Jni/Miir5G3a7G9MmjbEUASKJOhUlIFKqL1IqB81RBT/cv0bg9kAiy5VBF1WppxP/PwtjECzbeUi2Y1jbpYb98rnc/qmRO3ZJam9fDNcPpW09qGFhGgJIujca257F7G4guS2w/7haVzNoyRiwHzZ14oL8AIxHLMBSJJF19ULlsMAkROj9o9TnwhL9r4rX9sAWk28c5eq77+iVpmlT3yoRdZqvMqffzKiibDlzz95Gmms7V7mctxrhNVOOWTwMSJvk94Y9ZPenljKgPJIV3Z1cqqx+W8JxFFeelOuYvMEe4bOVBh1TepGzzdWVdYbylgXJy35uRTZ2drybUe5+jc0hiAuujHz0zdY1FwOHfwzSsSidlYn4syPeuytnxTzn7fbWXeXetTTtDlmLRf8MBSzXzDFWNH0cNGOCQ=="
            }
        },
        {
            "name": "file:/demo/configserver/application.yaml",
            "source": {
                "SharedPassword": "Fill_me_in"
            }
        }
    ],
    "state": null,
    "version": null
}

在这种情况下,如果配置客户端收到上述响应并请求该值 之共享密码来自环境它会拿回加密后的值,而不是Fill_me_in.spring-doc.cadn.net.cn