1. 程式人生 > >Eureak 開啟 HTTPS

Eureak 開啟 HTTPS

  上節說到,開啟 HTTP Basic 認證,但是這種基於 Base64 編碼的認證方式,如果被人截獲實在是太不安全了(如果是內網環境基本無所謂了)。這幾說說如何開啟 HTTPS 請求。

生成證書

  這裡是利用 JDK 自帶的工具生成證書檔案

生成服務端證書

$ keytool -genkeypair -alias EurekaServer -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore EurekaServer.p12 -validity 3650
輸入金鑰庫口令:
再次輸入新口令:
您的名字與姓氏是什麼?
  [Unknown]:  
您的組織單位名稱是什麼?
  [Unknown]:  
您的組織名稱是什麼?
  [Unknown]:  
您所在的城市或區域名稱是什麼?
  [Unknown]:  
您所在的省/市/自治區名稱是什麼?
  [Unknown]:  
該單位的雙字母國家/地區程式碼是什麼?
  [Unknown]:  
CN=郭青松, OU=杭州泡城網路有限公司, O=杭州泡城網路有限公司, L=上海市, ST=上海市, C=中國是否正確?
  [否]:  y

生成客戶端證書

$ keytool -genkeypair -alias EurekaClient -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore EurekaClient.p12 -validity 3650
輸入金鑰庫口令:
再次輸入新口令:
您的名字與姓氏是什麼?
  [Unknown]:  
您的組織單位名稱是什麼?
  [Unknown]:  
您的組織名稱是什麼?
  [Unknown]:  
您所在的城市或區域名稱是什麼?
  [Unknown]:  
您所在的省/市/自治區名稱是什麼?
  [Unknown]:  
該單位的雙字母國家/地區程式碼是什麼?
  [Unknown]:  
CN=郭青松, OU=杭州泡城網路有限公司, O=杭州泡城網路有限公司, L=上海市, ST=上海市, C=中國是否正確?
  [否]:  y

分別匯出證書

# 到處服務端證書
$ keytool -export -alias EurekaServer -file EurekaServer.crt --keystore EurekaServer.p12
輸入金鑰庫口令:
儲存在檔案 <EurekaServer.crt> 中的證書
# 到處客戶端證書
$ keytool -export -alias EurekaClient -file EurekaClient.crt --keystore EurekaClient.p12
輸入金鑰庫口令:
儲存在檔案 <EurekaClient.crt> 中的證書

互相信任證書

Client 信任 Server 的證書

$ keytool -import -alias EurekaServer -file EurekaServer.crt -keystore EurekaClient.p12
輸入金鑰庫口令: # 這裡輸入的是 EurekaClient.p12 口令
所有者: CN=***, OU=*****************, O=*****************, L=***, ST=***, C=中國
釋出者: CN=***, OU=*****************, O=*****************, L=***, ST=***, C=中國
序列號: 37e112f1
有效期開始日期: Tue Oct 23 15:35:11 CST 2018, 截止日期: Fri Oct 20 15:35:11 CST 2028
證書指紋:
	 MD5: 63:E7:78:B6:0D:BB:E6:F0:6D:B5:0E:DB:A5:57:0A:A7
	 SHA1: B1:8E:13:38:EB:85:DC:04:62:4C:6D:5F:BB:7A:FC:ED:02:32:B1:B3
	 SHA256: 99:F8:48:A5:C5:6D:23:57:C4:42:E0:88:93:66:93:03:82:A8:16:50:67:5B:BB:8F:5F:77:71:F1:2F:09:3D:34
	 簽名演算法名稱: SHA256withRSA
	 版本: 3

擴充套件:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 43 E8 01 85 30 17 2A 92   93 3B D3 2F 1C 98 ED 38  C...0.*..;./...8
0010: F1 EF 0A BD                                        ....
]
]

是否信任此證書? [否]:  y
證書已新增到金鑰庫中

Server 信任 Client 的證書

$ keytool -import -alias EurekaClient -file EurekaClient.crt -keystore EurekaServer.p12
輸入金鑰庫口令: # 這裡輸入的是 EurekaServer.p12 口令
所有者: CN=***, OU=*****************, O=*****************, L=***, ST=***, C=中國
釋出者: CN=***, OU=*****************, O=*****************, L=***, ST=***, C=中國
序列號: 7d59a572
有效期開始日期: Tue Oct 23 15:37:24 CST 2018, 截止日期: Fri Oct 20 15:37:24 CST 2028
證書指紋:
	 MD5: 81:51:73:FE:5D:F2:6F:0B:26:15:04:C2:2A:69:DC:E6
	 SHA1: 84:14:80:32:B4:BC:76:79:56:E0:49:49:83:E6:D8:1C:D4:75:5A:92
	 SHA256: F0:DA:C5:4D:F6:48:99:78:39:1D:EC:17:F4:61:81:AF:07:D1:6A:18:3A:12:48:39:12:ED:A2:0F:FB:7D:96:85
	 簽名演算法名稱: SHA256withRSA
	 版本: 3

擴充套件:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 4D 1F 9F 08 43 00 A4 6D   5C 8A 39 62 F8 D3 72 A9  M...C..m\.9b..r.
0010: 9A FD 3D 58                                        ..=X
]
]

是否信任此證書? [否]:  y
證書已新增到金鑰庫中

Eureka Server 配置

  把生成的 EurekaServer.p12 Copy 到 resources 下

配置檔案

server:
  # 專案埠號
  port: 8761
  # SSL 配置
  ssl:
    # 開啟 SSL 認證
    enabled: true
    # 證書別名 【注意這裡,別名只能小寫】
    key-alias: eurekaserver
    # 證書存放路徑
    key-store: classpath:EurekaServer.p12
    # 證書密碼
    key-store-password: 123456
    # 儲存型別
    key-store-type: PKCS12

spring:
  application:
    name: demo-eureka-server
  # 開啟安全控制
  security:
    user:
      # 使用者名稱
      name: eureka-server
      # 密碼
      password: 8e9lx7LuP3436gfsg

eureka:
  instance:
    # 主機名
    hostname: localhost
    # 使用 ip 註冊到註冊中心例項化
    prefer-ip-address: true
    # 安全埠
    secure-port: ${server.port}
    # 指示是否應為流量啟用安全埠
    secure-port-enabled: true
    # 關閉非安全埠
    non-secure-port-enabled: false
    home-page-url: https://${eureka.instance.hostname}:${server.port}/
    status-page-url: https://${eureka.instance.hostname}:${server.port}/actuator/info
    health-check-url: https://${eureka.instance.hostname}:${server.port}/actuator/health
  client:
    # 此例項是否從註冊中心獲取註冊資訊
    fetch-registry: false
    # 是否將此例項註冊到註冊中心
    register-with-eureka: false
    # 註冊地址
    service-url:
      # 預設註冊分割槽地址
      defaultZone: http://${eureka.instance.hostname}:8761/eureka/
  server:
    # 同步為空時,等待時間
    wait-time-in-ms-when-sync-empty: 0
    # 是否開啟自我保護機制
    ## 在分散式系統設計裡頭,通常需要對應用例項的存活進行健康檢查,這裡比較關鍵的問題就是要處理好網路偶爾抖動或短暫不可用時造成的誤判。另外Eureka Server端與Client端之間如果出現網路分割槽問題,在極端情況下可能會使得Eureka Server清空部分服務的例項列表,這個將嚴重影響到Eureka server的 availibility屬性。因此Eureka server引入了SELF PRESERVATION機制。
    ## Eureka client端與Server端之間有個租約,Client要定時傳送心跳來維持這個租約,表示自己還存活著。 Eureka通過當前註冊的例項數,去計算每分鐘應該從應用例項接收到的心跳數,如果最近一分鐘接收到的續約的次數小於指定閾值的話,則關閉租約失效剔除,禁止定時任務剔除失效的例項,從而保護註冊資訊。
    # 此處關閉可以防止問題(測試環境可以設定為false):Eureka server由於開啟並引入了SELF PRESERVATION模式,導致registry的資訊不會因為過期而被剔除掉,直到退出SELF PRESERVATION模式才能剔除。
    enable-self-preservation: false
    # 指定 Eviction Task 定時任務的排程頻率,用於剔除過期的例項,此處未使用預設頻率,頻率為:5/秒,預設為:60/秒
    # 有效防止的問題是:應用例項異常掛掉,沒能在掛掉之前告知Eureka server要下線掉該服務例項資訊。這個就需要依賴Eureka server的EvictionTask去剔除。
    eviction-interval-timer-in-ms: 5000
    # 設定read Write CacheMap的expire After Write引數,指定寫入多長時間後過期
    # 有效防止的問題是:應用例項下線時有告知Eureka server下線,但是由於Eureka server的REST API有response cache,因此需要等待快取過期才能更新
    response-cache-auto-expiration-in-seconds: 60
    # 此處不開啟快取,上方配置開啟一個即可
    # use-read-only-response-cache: false
    # 指定每分鐘需要收到的續約次數的閾值,預設值就是:0.85
    renewal-percent-threshold: 0.85
    # 續約頻率提高,預設:30
    leaseRenewalIntervalInseconds: 10

  啟動即可

Eureka Client 配置

  把生成的 EurekaClient.p12 Copy 到 resources 下

引入依賴

<!-- Http Client 支援 -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

配置檔案

server:
  # 專案埠號
  port: 11100

spring:
  application:
    # Spring Boot 專案例項名稱
    name: demo-order

### 註冊中心配置
eureka:
  instance:
    # 主機名
    hostname: localhost
    # 使用 ip 註冊到註冊中心例項化
    prefer-ip-address: true
  client:
    secure-port-enabled: ture
    ssl:
      key-store: classpath:EurekaClient.p12
      key-password: 123456
    security:
      user:
        name: eureka-server
        password: 8e9lx7LuP3436gfsg
    # Spring Cloud Eureka 註冊中心地址
    service-url:
      defaultZone: http://${eureka.client.security.user.name}:${eureka.client.security.user.password}@${eureka.instance.hostname}:8761/eureka/
    # 針對新服務上線, Eureka client獲取不及時的問題,在測試環境,可以適當提高Client端拉取Server註冊資訊的頻率,預設:30秒
    registry-fetch-interval-seconds: 30

  這裡的配置是通過幾個自定義的引數來進行配置的證書資訊,並沒有做全域性的 HTTPS 啟用操作。

  • eureka.client.secure-port-enabled:是否開啟安全埠訪問
  • eureka.client.ssl.key-store:證書檔案
  • eureka.client.ssl.key-password:證書密碼

  接下來在程式碼中進行配置 HTTPS

/**
 * @Author:大漠知秋
 * @Description:Eureka Client HTTPS 配置
 * @CreateDate:4:13 PM 2018/10/23
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "eureka.client.ssl")
public class EurekaHttpsClientConfiguration {

    private String keyStore;

    private String keyStorePassword;

    @Bean
    @ConditionalOnProperty(
            value = "eureka.client.secure-port-enabled",
            havingValue = "true"
    )
    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(this.keyStore), this.keyStorePassword.toCharArray()
                )
                .build();
        builder.withCustomSSL(sslContext);

        builder.withMaxTotalConnections(10);
        builder.withMaxConnectionsPerHost(10);

        DiscoveryClient.DiscoveryClientOptionalArgs args = new DiscoveryClient.DiscoveryClientOptionalArgs();
        args.setEurekaJerseyClient(builder.build());
        return args;
    }

}

  啟動即可