写于:2019-01-12 00:00:37
code.7z
一、Spring Cloud Config 数据传输安全
针对数据传输的问题,在保证内网访问的前提下,相对而言,数据的安全还是相对比较可靠的。
不过为了让数据不以明文的方式进行传输,可以通过 Spring Cloud 支持的加密属性对配置进行加密操作。
二、两种加密方式案例
以上述案例代码进行拓展。
2.1、对称加密
模拟对 clietn 端
spring.application.name配置的加密
服务端操作
step1、服务端 config Server bootstrap.properties 中追加配置
## 对称加密秘钥 keyencrypt.key = symmetrical_encryption_key
step2、启动服务端服务,在 postman 中进行操作
访问API http://localhost:28080/encrypt
对需要加密的内容进行加密操作
客户端操作
更改配置文件中 spring.application.name 参数为加密后的密文
如下:
需要在密文前加
{cipher},否则不生效
通过服务端验证密文被解密
访问 http://localhost:28080/config-cliet/default 结果如下:
{"name": "config-client","profiles": ["default"],"label": null,"version": "261eed1c431d0f9365e994a8b57e840e91b1b65b","state": null,"propertySources": [{"name": "xxxxxx/case-1/config-client/config-client.properties","source": {"spring.cloud.config.profile": "default","server.port": "9991","spring.application.name": "config-clien-default"}}]}
能够发现,此时的 spring.application.name 为明文显示。
2.2、非对称加密(RSA)
服务端操作
step1、生成 RSA 文件
keytool -genkeypair -alias config-server-key -keyalg RSA -dname "CN=Config Server,OU=QGF,L=Beijing,S=Beijing,C=CN" -keypass zhixing -keystore config-server.jks -storepass ZHIXING
参数详解:
-genkeypair 参数即产生一对public key和private key。-keyalg 指定生成key的算法,这里使用默认的RSA-dname 指定common name,即CN,用以验证key的身份。其中各项皆为自定义参数,OU为单位名称,O为组织名称,L为城市,S为省份/州,C为国家-keypass 为key的密码-keystore 为keystore的文件名-storepass 访问keystore的密码
step2、生成 config-server.jks 放入 服务端项目 resources 中,同时 pom 追加如下配置:
pom 文件配置 (否则无法加载 jks 文件)
<build><resources><resource><directory>src/main/resources</directory><filtering>true</filtering><excludes><exclude>**/*.jks</exclude></excludes></resource><resource><directory>src/main/resources</directory><filtering>false</filtering><includes><include>**/*.jks</include></includes></resource></resources></build>
step3、配置 bootstrap.properties (记得注释掉 对称加密的配置(对称和非对称不能同时存在))
## 放置在 resources 中的文件名encrypt.key-store.location = config-server.jks## 对应 keystoreencrypt.key-store.alias = config-server-key## 对应 -storepassencrypt.key-store.password = ZHIXING## 对应 -keypassencrypt.key-store.secret = zhixing
step4、启动服务端服务,在 postman 中进行操作
访问API http://localhost:28080/encrypt
对需要加密的内容进行加密操作
客户端操作
更改配置文件中 spring.application.name 参数为加密后的密文
如下:
需要在密文前加
{cipher},否则不生效
三、扩展:配置文件加解密源码分析
3.1、Config Server 提供的 API
在 Spring Cloud Config 中提供了两套 API 接口,为 EnvironmentController, EncryptionController
EnvironmentController:为获取配置文件配置属性提供 APIEncryptionController:提供单个字符的加解密功能
两套 API 的操作是相关联的,将需要加密的字符通过EncryptionController进行加密,客户端通过EnvironmentController拉取的配置的时候,如果有需要解密的配置,加通过相同的算法进行解密
EncryptionController 部分代码
@RestController@RequestMapping(path = "${spring.cloud.config.server.prefix:}")public class EncryptionController {volatile private TextEncryptorLocator encryptor;@RequestMapping(value = "/encrypt/{name}/{profiles}", method = RequestMethod.POST)public String encrypt(@PathVariable String name, @PathVariable String profiles,@RequestBody String data, @RequestHeader("Content-Type") MediaType type) {......String encrypted = this.helper.addPrefix(keys,this.encryptor.locate(keys).encrypt(textToEncrypt));logger.info("Encrypted data");return encrypted;}@RequestMapping(value = "/decrypt/{name}/{profiles}", method = RequestMethod.POST)public String decrypt(@PathVariable String name, @PathVariable String profiles,@RequestBody String data, @RequestHeader("Content-Type") MediaType type) {......TextEncryptor encryptor = this.encryptor.locate(encryptorKeys);return decrypted;}}
上述代码主要两个 API
- encrypt 字符加密API
- decrypt 字符解密API
而加解密的操作均由 TextEncryptorLocator 来实现
EnvironmentController 部分代码
*/@RestController@RequestMapping(method = RequestMethod.GET, path = "${spring.cloud.config.server.prefix:}")public class EnvironmentController {private EnvironmentRepository repository;@RequestMapping("/{name}/{profiles}/{label:.*}")public Environment labelled(@PathVariable String name, @PathVariable String profiles,@PathVariable String label) {......Environment environment = this.repository.findOne(name, profiles, label);......return environment;}}
通过
EnvironmentController的配置类能够知道该类中的EnvironmentRepository参数实现类为EnvironmentEncryptorEnvironmentRepository
关键对象关系如下:
获取 Environment 环境对象 UML图
3.2、提供加解密功能的代码组
关键类 TextEncryptorLocator 和 TextEncryptor 。
TextEncryptorLocator : 加解密定位器,持有 TextEncryptor 实例对象
TextEncryptor: 真正进行加解密操作的类。
相关代码如下:
两者的关联:通过 TextEncryptorLocator#locate 定位到指定的 TextEncryptor,然后由 TextEncryptor 进行加解密操作。
通过自动配置查找相关的配置信息
在 Spring Cloud Config 中 TextEncryptor 的配置类 DefaultTextEncryptorConfiguration 代码如下:
@ConditionalOnMissingBean(TextEncryptor.class)@Configurationclass DefaultTextEncryptorConfiguration {@Autowiredprivate KeyProperties key;@Autowired(required = false)private TextEncryptorLocator locator;@Beanpublic TextEncryptor defaultTextEncryptor() {// 如果存在 RSA 非对称加密,if (this.locator != null) {return new LocatorTextEncryptor(this.locator);}// 如果 encrypt.key 配置存在,则为 AES 对称加密if (StringUtils.hasText(this.key.getKey())) {return new EncryptorFactory(this.key.getSalt()).create(this.key.getKey());}// 都不存在,则为空实现,也就是没有加解密功能的空实现return Encryptors.noOpText();}}
上述配置描述了加解密算法的相关配置顺序:
- 非对称加密-RSA 优先
- 对称加密-AES 其次
- 在没有的话,就是一个空实现
NoOpTextEncryptor
对称加密(AES)
非对称加密的代码对象为 SingleTextEncryptorLocator 和 HexEncodingTextEncryptor
这里的
HexEncodingTextEncryptor采用的委派的方式,将加解密操作委派给了AesBytesEncryptor来实现
代码实现对象结构如下
非对称解密的流程,UML 流程图如下
具体操作可以看代码,代码很直观
非对称加密(RSA)
代码实现对象结构如下:
执行 RSA 加解密的流程包含了三个对象
LocatorTextEncryptor,KeyStoreTextEncryptorLocator和RsaSecretEncryptor
以 RSA 解密流程为主,UML 流程图如下:
具体操作可以看代码,代码很直观
