持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情
23、配置的加密和解密
一、配置的加密解密
在实际应用中会涉及很多敏感的数据,这些数据会被加密保存到 SVN仓库中,最常见 的就是数据库密码 Spring Cloud Config 为这类敏感数据提供了加密和解密的功能,加密后 的密文在传输给客户端前会进行解密 配置服务器支持对称加密和非对称加密,对称加密 使用 AES 算法,非对称加密使用 RSA 算法。
1、为服务器安装 JCE
服务器的加密和解密依赖JCE (Java Cryptography Extension ),可到 Oracle 官方网站下载Java 8 JCE ,文件名为 jce_policy-8.zip。
下载了zip包之后 ,解压会得到 local_policy.jar和US_export_policy.jar两个jar包。解压后,进入%JDK_HOME%\jre\lib\security,(windows不用覆盖)覆盖local_policy.jar和US_export_policy.jar两个jar包即可,即可完成安装。
2、加密和解密端点
对称加密 Dalston.SR3、Dalston.SR2版本不能对配置文件加密,若需要调整到Dalston.SR1或者期待Dalston.SR4的发布
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
小节以对称加密为基础,介绍下配置服务器提供的加密和解密端点,这两个端点 可以当作工具来使用,方便我们进行加密和解密。修改配置服务器(spring-config-server) bootstrap. yml 文件,设置加密和解密的 key ,请见代码清单 ;
必须是bootsrap文件,application文件不起作用 # application覆盖不了boostrap里的配置,boostrap覆盖application # 配置中心使用了bootstrap,就必须把仓库路径/spring.application.name/ 加密/解密信息 放在 bootstrap 里 # 如果不放在这,就会启动异常 # encrypt.key=myKey 配置在 bootstrap 里才会生效,在 application 里不会生效
如果在application文件里配置:出现如下异常:
{"description":"No key was installed for encryption service","status":"NO_KEY"}
#设置加密和解密的key,对称加密
encrypt.key=myKey
加密的服务端点为 /encrypt ,需要向该端点发送 POST 请求。请求体中包含需要加密的 明文 ,我们使用 HttpClient 来向该端点发送请求,请见代码清单:
public static void main(String[] args) throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
// 发送post请求
HttpPost post = new HttpPost("http://localhost:8888/encrypt");
// 设置请求的参数,对crazyit进行加密,编码格式为UTF-8
HttpEntity entity = new StringEntity("crazyit", Consts.UTF_8);
post.setEntity(entity);
// 获取响应
HttpResponse response = client.execute(post);
// 根据响应解析出字符串 -- 加密后的
System.out.println(EntityUtils.toString(response.getEntity()));
}
在代码清单 9-8 中,向/encrypt 端点发送 POST 请求,请求为 crazyit 字符串进行加密。启动配置服务器( spring-config-server 端口为 8888 ),再运行代码清单。控制台输出如下:
f47f619fbb809d393f6f4c188d0dfa4453257fc9a3f92c65fdb54502e9ab3b43
访问的 /encrypt 端点会使用配置的 key 对明文进行加密并返回密文。接下来,测试解密端点 /decrypt ,同样使用 HttpClient 访问该端点,请见代码清单
public static void main0(String[] args) throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
// 发送post请求
HttpPost post = new HttpPost("http://localhost:8888/decrypt");
// 设置请求的参数,对字符串进行解密,编码格式为UTF-8
HttpEntity entity = new StringEntity("f47f619fbb809d393f6f4c188d0dfa4453257fc9a3f92c65fdb54502e9ab3b43", Consts.UTF_8);
post.setEntity(entity);
// 获取响应
HttpResponse response = client.execute(post);
// 根据响应解析出字符串 -- 解密后的
System.out.println(EntityUtils.toString(response.getEntity()));
}
调用 /decrypt 端点时,向其 POST 密文,用我们配置的 key 对密文进行解密,最后返回
解密后的明文。 结果是 crazyit
**本例相当于加密解密端口当作工具,对 HttpEntity 进行加密解密,response.getEntity()返回的也是 HttpEntity **
RequestEntity和RequestBody区别,httpclient的poseMethod提交数据,httpclient3.1采用RequestEntity接口替代以前的RequestBody。
HttpEntity其实相当于一个消息实体,内容是http传送的报文(这里可以说是html,css等等文件)。这里只需要知道它是用来表征一个http报文的实体就行了,用来发送或接收。
3、SVN存储加密数据
对称加密 在SVN 仓库的 yml (properties )配置文件中,使用 "{cipher}密文" 的格式来保存加密后 的数据。假设 MySQL 数据库的密码为 crazyit ,服务器中配置的 key 为 myKey ,对 crazyit 字符串加密后的密文为4c8a549def2916530191798f23e697afd0ee76609723363709849649a63c8118 。 为 SVN 仓库中的 test-project/default-config/first-test.yml 文件进行以下配置:
yml文件配置:
mysql:
passwd:'{cipher}4c8a549def2916530191798f23e697afd0ee76609723363709849649a63c8118'
properties文件配置,不需要单引号:
mysql.passwd={cipher}4c8a549def2916530191798f23e697afd0ee76609723363709849649a63c8118
启动配置服务器,在浏览器中访问:http://localhost:8888/first-test.properties ,配置服务器会自动安装 前面配置的 key 为 myKey 进行解密。结果如下:
mysql.passwd: crazyit
4、非对称加密
对称加密算法在加密和解密时都使用同一个密钥,而非对称加密则使用一对密钥。使用公钥加密时,解密就需要使用私钥。 Spring Cloud Config 同样支持非对称加密,使用keytool 工具生成一对密钥用于加密和解密,在CMD控制台输入以下命令:
keytool -genkeypair -alias "testKey" -keyalg "RSA" -keystore "D:\myTest.keystore"
- 密钥库的密码至少必须6个字符,可以是纯数字或者字母或者数字和字母的组合等等
- "名字与姓氏"应该是输入域名,而不是我们的个人姓名,其他的可以不填 本例:localhost
接提示输入相关信息后,将生成的 myTest.keystore 复制到配置服务器的 classpath 下(本例与 application. properties 同目录),修改 application.properties 文件,加入以下内容:
# keystore 位置
encrypt.key-store.location=classpath:/myTest.keystore
# 密钥库的密码 -- 需要与CMD命令窗口一致
encrypt.key-store.password=crazyit
# 密钥对的别名 -- 与执行命令一致
encrypt.key-store.alias=testKey
# 密钥口令 -- 与执行命令一致
encrypt.key-store.secret=crazyit
完成 以上工作后,启动配置服务器,向 :http://localhost:8888/encrypt(加密端点)发送POST 请求,可以得到加密后的密文。密文的使用与前面的对称加密类似,在 SVN 的配置文件中同样使用 "{cipher}密文" 的格式(注意 yml 文件需要单引号),访问相应配置时,配置服务器会自动进行解密。
配置:
mysql.passwd={cipher}AQCFAtSjWfEdpaymekrACLKMm+bkvFknxcrZUepHA3fwItATeMjbYx4Nv8SXsU1j1ewz5J3tTSU56s/m4tFHyEILmr7pFZeTqRdtIot1GM9I3E+IBBjC0EBWKDPuCzivKbQAzsnCIE00HpkA3iZ4RukQi+8arNuAW+0xLnF/dVCC+8XoY6Xlk7g+M8qXguXQ7azzmU1uvVr3xqFG4dz+xM37APKsz53eDFLB352A6/hrngZ9qRjzWCm7QSCADJtxrcrkYqCq7AoUy9ux5PkDlO/RqXq1TDUGcboMvgr600EmOTkN56ol0jtqINNYTm79DhkhZiEAlcXuUj77vK9H+TKaxHgel55588Jz+DzOuY0kvcbJkWIaVi0nwpH//8hg3as=
访问:http://localhost:8888/first-test.properties 得到 mysql.passwd: crazyit
对称加密 和 非对称加密只能使用一个,配置了 keystore ,对称加密的配置:encrypt.key=myKey就会失效,无法解密。