Eureka实战-5【启用https】
上一篇主要说的是开启http basic认证,从安全角度来讲,基于base64编码,容易被抓包后破解,在公网中很不安全,本文详谈如何在eureka server和eureka client中开启https。
公共依赖pom文件
<parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.0.3.release</version> <relativepath/> </parent> <properties> <project.build.sourceencoding>utf-8</project.build.sourceencoding> <project.reporting.outputencoding>utf-8</project.reporting.outputencoding> <java.version>1.8</java.version> <spring-cloud.version>finchley.release</spring-cloud.version> </properties> <dependencymanagement> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-dependencies</artifactid> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencymanagement>
1、eureka server工程
1.1、eureka server工程pom:
<!--加上文章头部的公共依赖-->
<dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-netflix-eureka-server</artifactid> </dependency> </dependencies> <build> <plugins> <plugin> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifactid> </plugin> </plugins> </build>
1.2、eureka server工程启动类:
import org.springframework.boot.springapplication; import org.springframework.boot.autoconfigure.springbootapplication; import org.springframework.cloud.netflix.eureka.server.enableeurekaserver; @springbootapplication @enableeurekaserver public class eurekaserverapplication { public static void main(string[] args) { springapplication.run(eurekaserverapplication.class, args); } }
1.3、生成证书
a、生成server工程的证书,使用命令行工具,执行下面的指令:
keytool -genkeypair -alias server -storetype pkcs12 -keyalg rsa -keysize 2048 -keystore server.p12 -validity 3650 输入密钥库口令: 再次输入新口令: 您的名字与姓氏是什么? [unknown]: spring 您的组织单位名称是什么? [unknown]: spring 您的组织名称是什么? [unknown]: spring 您所在的城市或区域名称是什么? [unknown]: spring 您所在的省/市/自治区名称是什么? [unknown]: spring 该单位的双字母国家/地区代码是什么? [unknown]: spring cn=spring, ou=spring, o=spring, l=spring, st=spring, c=spring是否正确? [否]: y
b、同样的方式生成client工程证书,执行下面的指令:
keytool -genkeypair -alias client -storetype pkcs12 -keyalg rsa -keysize 2048 -keystore client.p12 -validity 3650
//。。。同样需要设置密码,回答上面的那些问题
c、分别导出2个p12证书,执行指令:
keytool -export -alias server -file server.crt --keystore server.p12 输入密钥库口令: 这里的密码是生成server证书时设置的密码 存储在文件 <server.crt> 中的证书
keytool -export -alias client -file client.crt --keystore client.p12 输入密钥库口令: 这里的密码是生成client证书时设置的密码 存储在文件 <client.crt> 中的证书
d、将server.crt文件导入client.p12证书中,使client端信任server的证书,执行如下指令
keytool -import -alias server -file server.crt -keystore client.p12 输入密钥库口令: 这里的密码是生成client证书密码,密码错误会提示如下信息: 【密码错误时提示的信息:keytool 错误: java.io.ioexception: keystore password was incorrect】
所有者: cn=spring, ou=spring, o=spring, l=spring, st=spring, c=spring 发布者: cn=spring, ou=spring, o=spring, l=spring, st=spring, c=spring 序列号: 2b87a269 有效期为 fri oct 04 20:11:07 cst 2019 至 mon oct 01 20:11:07 cst 2029 证书指纹: md5: ef:a3:6b:32:de:8f:e4:34:46:e6:0d:48:b9:8f:b8:7e sha1: ae:42:78:14:d8:6b:b2:e9:46:f4:76:e8:d9:d0:51:e0:3a:e6:c9:2e sha256: 54:6d:93:7e:b3:d3:c4:49:87:84:9d:46:66:b1:b8:1b:95:5b:dc:05:9a:8a:a4:df:43:e4:a7:a7:4a:81:f7:b0 签名算法名称: sha256withrsa 主体公共密钥算法: 2048 位 rsa 密钥 版本: 3 扩展: #1: objectid: 2.5.29.14 criticality=false subjectkeyidentifier [ keyidentifier [ 0000: 6c 1a e4 01 eb 84 0b c2 90 97 81 3d db 0d c3 f1 l..........=.... 0010: 4a fb 2a f4 j.*. ] ] 是否信任此证书? [否]: y 证书已添加到密钥库中
e、将client.crt文件导入server.p12文件,使server服务信任client的证书,执行如下指令:
keytool -import -alias client -file client.crt -keystore server.p12 输入密钥库口令: 这里的密码是生成server证书密码 所有者: cn=cloud, ou=cloud, o=cloud, l=cloud, st=cloud, c=cloud 发布者: cn=cloud, ou=cloud, o=cloud, l=cloud, st=cloud, c=cloud 序列号: 6ea2a01 有效期为 fri oct 04 20:27:38 cst 2019 至 mon oct 01 20:27:38 cst 2029 证书指纹: md5: e9:22:2c:8d:c4:08:27:ad:02:75:93:31:c2:17:35:8e sha1: bb:b0:9a:3a:98:43:5e:02:fc:8a:bc:85:33:dd:82:4a:4e:df:3a:5c sha256: 20:96:61:27:d1:ca:55:e5:b6:0e:41:ca:bc:84:f8:8f:1f:d8:25:87:10:50:90:e3:bc:12:39:35:74:16:4a:b3 签名算法名称: sha256withrsa 主体公共密钥算法: 2048 位 rsa 密钥 版本: 3 扩展: #1: objectid: 2.5.29.14 criticality=false subjectkeyidentifier [ keyidentifier [ 0000: 91 e6 46 ef 4c 9e 88 b1 2f 63 12 4b 39 53 9d 32 ..f.l.../c.k9s.2 0010: ef 0f 42 f9 ..b. ] ] 是否信任此证书? [否]: y 证书已添加到密钥库中
1.4、将生成的server.p12、server.crt、client.crt三个文件放在eureka server工程resources目录下。
1.5、添加eureka server工程相关resources配置文件
application-https.yml:
server: port: 8766 ssl: enabled: true key-store: classpath:server.p12 key-store-password: hello2019 #生成server证书时设置的密码 key-store-type: pkcs12 key-alias: server eureka: instance: hostname: localhost secureport: ${server.port} secureportenabled: true nonsecureportenabled: false homepageurl: https://${eureka.instance.hostname}:${server.port}/ statuspageurl: https://${eureka.instance.hostname}:${server.port}/ client: registerwitheureka: false fetchregistry: false serviceurl: defaultzone: https://${eureka.instance.hostname}:${server.port}/eureka/ server: waittimeinmswhensyncempty: 0 enableselfpreservation: false
application.yml:
spring: profiles: active: https
1.6、启动eureka server工程,执行指令:
mvn spring-boot:run -dspring.profiles.active=https
访问:https://localhost:8766
由此看出确实使用的是https,不妨在试一下访问:http://localhost:8766
2、eureka client工程
2.1、client工程pom文件:
<!--加上文章头部的公共依赖-->
<dependencies> <dependency> <groupid>org.apache.httpcomponents</groupid> <artifactid>httpclient</artifactid> <version>4.5.5</version> </dependency> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-netflix-eureka-client</artifactid> </dependency> </dependencies> <build> <plugins> <plugin> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifactid> </plugin> </plugins> </build>
2.2、client工程启动类:
import org.springframework.boot.springapplication; import org.springframework.boot.autoconfigure.springbootapplication; import org.springframework.cloud.netflix.eureka.enableeurekaclient; @springbootapplication @enableeurekaclient public class eurekaclientapplication { public static void main(string[] args) { springapplication.run(eurekaclientapplication.class, args); } }
2.2、client工程resources配置文件
先将client.crt、client.p12、server.crt三个文件放在client工程的resources目录下。
application.yml:
spring: profiles: active: https
application-https.yml:
server: port: 8081 spring: application: name: client1 eureka: client: secureportenabled: true ssl: key-store: client.p12 key-store-password: hello2020 serviceurl: defaultzone: https://localhost:8766/eureka/
这里没有指定整个应用实例启用https,仅仅是开启访问eureka server的https配置,自定义eureka.client.ssl.key-store和eureka.client.ssl.key-store-password两个属性,指定client访问server的sslcontext配置,需要在代码里指定discoveryclient.discoveryclientoptionalargs:
import com.netflix.discovery.discoveryclient; import com.netflix.discovery.shared.transport.jersey.eurekajerseyclientimpl; import org.apache.http.ssl.sslcontextbuilder; import org.springframework.beans.factory.annotation.value; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.context.annotation.profile; import javax.net.ssl.sslcontext; import java.io.ioexception; import java.security.keymanagementexception; import java.security.keystoreexception; import java.security.nosuchalgorithmexception; import java.security.cert.certificateexception; /** * 指定client访问server的sslcontext配置 */ @profile({"https"}) @configuration public class eurekahttpsclientconfig { @value("${eureka.client.ssl.key-store}") string keystorefilename; @value("${eureka.client.ssl.key-store-password}") string keystorepassword; @bean public discoveryclient.discoveryclientoptionalargs discoveryclientoptionalargs() throws certificateexception, nosuchalgorithmexception, keystoreexception, ioexception, keymanagementexception { eurekajerseyclientimpl.eurekajerseyclientbuilder builder = new eurekajerseyclientimpl.eurekajerseyclientbuilder(); builder.withclientname("eureka-https-client"); sslcontext sslcontext = new sslcontextbuilder() .loadtrustmaterial( this.getclass().getclassloader().getresource(keystorefilename),keystorepassword.tochararray() ) .build(); builder.withcustomssl(sslcontext); builder.withmaxtotalconnections(10); builder.withmaxconnectionsperhost(10); discoveryclient.discoveryclientoptionalargs args = new discoveryclient.discoveryclientoptionalargs(); args.seteurekajerseyclient(builder.build()); return args; } }
2.3、执行指令,启动client工程:
mvn spring-boot:run -dspring.profiles.active=https
访问https://localhost:8766/
可以看到client工程已经成功注册到了server服务上。