Eureka开启https实践
编辑前言
本篇主要整理了eureka server如何开启https,以及eureka client之前如何通过https进行访问。
测试工程
本次主要涉及三个工程,一个是Eureka Server注册中心:eurekaServer,两个Eureka Client:client-1和server-1,并且由client-1去调用server-1提供的服务。
Eureka Server 、Eureka Client证书生成
首先需要生成每个服务对应访问的证书,采用本地证书生成的方式,本案例共生成了四份证书,分别是eurekaServer的证书:eurekaServer.keystore,client-1的证书:client1.keystore,server-1的证书:server1.keystore,信任库证书:trustStore.store。
具体生成证书的命令如下:
keytool -genkey -alias eurekaServer -storetype JKS -keyalg RSA -keysize 2048 -keystore ./eurekaServer.keystore -validity 3650
证书生成: 部分参数说明:
-alias:指定生成证书的别名
-storetype:指定秘钥仓库类型
-keysize:指定证书大小
-keystore:指定生成的证书文件的存储路径
-validity:指定证书的有效期
EurekaServer工程配置
将证书文件放到项目的resources目录下:
在配置文件中添加如下参数:
ssl:
enabled: true # 开始ssl认证
key-alias: eurekaServer # 证书别名
key-store: classpath:eurekaServer.keystore # 证书位置
key-store-type: JKS # 秘钥库存储类型
key-store-password: 123456 # 秘钥库口令
添加完如下参数之后,再次启动eurekaServer服务,浏览器访问eurekaServer地址,发现已经是https的了。证书是我们自己本地生成的,不被浏览器识别,所以是不安全的,我们目前也只是测试使用。
还要设置一下下面的参数开启服务发现https的支持,这边贴一下参考地址:https://cloud.spring.io/spring-cloud-static/spring-cloud.html#_registering_a_secure_application, 英文好的可以自己读一读~
eureka:
instance:
statusPageUrl: https://${eureka.instance.hostname}:${server.port}/info
healthCheckUrl: https://${eureka.instance.hostname}:${server.port}/health
homePageUrl: https://${eureka.instance.hostname}:${server.port}/
hostname: localhost
Eureka Client工程配置,注册到Eureka Server
开启https访问和上面一样,将各自的证书放到resources目录,并且添加配置文件。
server:
ssl:
enabled: true # 开始ssl认证
key-alias: client1 # 证书别名
key-store: classpath:client1.keystore # 证书位置
key-store-type: JKS # 秘钥库存储类型
key-store-password: 123456 # 秘钥库口令
server:
ssl:
enabled: true # 开始ssl认证
key-alias: server1 # 证书别名
key-store: classpath:server1.keystore # 证书位置
key-store-type: JKS # 秘钥库存储类型
key-store-password: 123456 # 秘钥库口令
通过https注册到eureka上首先需要将eureka的地址修改为https。
eureka:
client:
service-url:
defaultZone: https://localhost:8761/eureka
之后需要将eureka的证书添加到trustStore.keystore信任库中,并通过https注册到eureka,具体操作步骤如下:
第一步,将eurekaServer.keystore导出为cer证书文件
keytool -exportcert -v -alias eurekaServer -keystore eurekaServer.keystore -storepass 123456 -file eurekaServer.cer
第二步,将导出的cer证书文件加入到trustStore信任库中
keytool -import -alias eurekaServer -keystore trustStore.keystore -file eurekaServer.cer
第三步,将信任库trustStore.keystore添加到client-1,server-1工程的resources目录
第四步,配置信任库相关配置文件
server:
ssl:
trust-store: classpath:trustStore.keystore # 信任库证书位置
trust-store-type: JKS # 信任库秘钥存储类型
trust-store-password: 123456 # 秘钥库口令
第五步,注入一个DiscoveryClientOptionalArgs的bean,同时设置其SSLContext的trustStore属性为设置的信任库的信息
具体代码:
/**
* SSLContext对象 设置了信任库信息
*
* @author yuanzhihao
* @since 2021/11/26
*/
@Configuration
public class SSLContextConfig {
@Value("${server.ssl.trust-store}")
private String trustStorePath;
@Value("${server.ssl.trust-store-password}")
private String trustStorePassword;
@Bean
public SSLContext sslContext() throws Exception {
return SSLContextBuilder.
create().
loadTrustMaterial(ResourceUtils.getFile(trustStorePath), trustStorePassword.toCharArray()).
build();
}
}
// 注入一个discoveryClientOptionalArgs通过https的方式注册到eureka
@Bean
public DiscoveryClient.DiscoveryClientOptionalArgs discoveryClientOptionalArgs(SSLContext sslContext) {
DiscoveryClient.DiscoveryClientOptionalArgs discoveryClientOptionalArgs = new DiscoveryClient.DiscoveryClientOptionalArgs();
discoveryClientOptionalArgs.setSSLContext(sslContext);
return discoveryClientOptionalArgs;
}
最后,启动所有服务,可以看到微服务已经通过https注册到了eureka上面,https启用完成!
微服务之前通过https互相调用
上面完成了微服务通过https注册到eureka上面,下面在详细说明下各个微服务之前如何通过https去进行调用,现在假设的场景是client-1去调用server-1的接口。
首先,和上面类似,client-1去调用server-1的接口需要将server-1的证书添加到client-1的信任库trustStore.keystore中
# 导出server1的证书文件
keytool -exportcert -v -alias server1 -keystore server1.keystore -storepass 123456 -file server1.cer
# 将导出的cer证书文件加入到trustStore信任库中
keytool -import -alias server1 -keystore trustStore.keystore -file server1.cer
可以通过keytool -list -keystore ${keystore}查看秘钥库存在哪些证书
将更新之后的trustStore.keystore重新替换到client1的resources目录下
微服务之间的调用通过resttemplate的方式,在注入resttemplate对象的时候,同时设置SSLContext,添加了信任库的信息
@Bean
@LoadBalanced
public RestTemplate restTemplate(SSLContext sslContext) {
CloseableHttpClient build = HttpClients.custom().setSSLContext(sslContext).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(build);
return new RestTemplate(factory);
}
之后,就可以通过https://{applicationName}/{path}的方式去进行微服务之间的调用,client-1调用了server-1的twoDog接口
@GetMapping("twoDog")
public Dog twoDog() {
log.info("hahaa");
final ResponseEntity<Dog> forEntity = restTemplate.getForEntity("https://eureka-server1/server1/twoDog",
Dog.class);
return forEntity.getBody();
}
调用OK!
结语
这边是自己学习过程的一个整理,如果有什么不对的地方还请大家多多指点!