真——Springcloud支持Https


很久不寫了,因為一直沒有一個項目的需求推動,擔心寫的東西可能不是太實際。其間學習的事倒是做了不少,設計模式、領域開發、Antlr、kubernetes等等,其實大部分都記在紙質筆記上了。。

基於對新技術的向往,以及微服務生態功能的對比調研,在技術選型上我站邊Springcloud,隨之而來的大量架構設計工作,部署監控工作,路漫漫其修遠兮。

小公司的小組長不太好當,需求分析、計划排期、架構、模塊類圖、數據庫表、安全、部署、監控都要做。

前一天boss找我,說我們之前的前后端交互太暴露了,明文密碼,明文傳輸,安全隱患很大。鑒於我們現在的微服務架構選擇了Springcloud,能不能讓它支持https,密碼的事另做方案。

這自然是個修煉的機會啊。開始。

 

先說下角色指代:

Eureka:注冊中心 server

Config:配置中心

consumer:client

producer:client

gateway:Zuul網關

 

首先,明確目標,網上大部分標題硬核晃眼的文章實際上只做滿足一半目標的事情,而且普遍做一半還會出錯,貼代碼往往不給出引用的包,也不說明版本。通通讓讀者去猜。

故我把Springcloud支持Https這件事情分為三個小目標。

1、正確注冊到Eureka

判斷標准:Config啟動后Eureka有顯示

這一步需要生成證書並添加信任,要讓Java運行時信任自己生成的證書(默認還會跑到那里去找),其實應該可以做到程序里,不過資料較少,加在哪里需要研究下。

#生成keystore,注意SAN很重要,https地址如不包含在此處,使用時則會報錯

keytool -genkey -alias server -keyalg RSA -storetype PKCS12 -keystore serverkeystore.p12 -ext SAN=dns:localhost,ip:127.0.0.1

#導出alias為server的證書
keytool -export -alias server -file servercert.cer -keystore serverkeystore.p12

#將證書添加至jre信任秘鑰庫(alias可以不為server)
keytool -import -alias server -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file servercert.cer

 

然后在Eureka和Config的springboot配置文件中指明https注冊,

eureka.instance.hostname=localhost

#主要是這兩條
eureka.instance.secure-port-enabled=true
eureka.instance.non-secure-port-enabled=false

#因為有默認值所以要覆蓋下
eureka.instance.status-page-url=https://${eureka.instance.hostname}:${server.port}/info
eureka.instance.health-check-url=https://${eureka.instance.hostname}:${server.port}/health
eureka.instance.home-page-url=https://${eureka.instance.hostname}:${server.port}/

 

再配置ssl秘鑰庫,

server.ssl.key-store=classpath:serverkeystore.p12
server.ssl.key-store-password=123456
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias=server

此時,springboot應該默認采用https方式注冊了。

因為是自己簽發的證書,如果不爽瀏覽器的安全提示,可以在瀏覽器中添加一下證書根節點。

但是,朋友們,我們的目的不是instance成功注冊而是去取注冊中心的instance信息對嗎。

 

2、從Eureka取到各client的https地址和端口

例:正確從Config讀取配置即可

發現這時的問題是consumer或producer取不到Instance的正確端口,

比如consumer通過spring.cloud.config.discovery.serviceId就找不到Config的instance,改成spring.cloud.config.uri直接指定Config的https地址就沒問題。

原因就在這條配置,eureka把http和https的通信端口設置分開了:

#安全通信端口(默認443)

eureka.instance.securePort=your port

也許還有一條對你起作用的配置:

#是否優先使用IP地址作為主機名的標識,默認false(當然,如果你生成秘鑰的SAN包含當前ip那也無妨)

#eureka.instance.prefer-ip-address=true

此時consumer或producer可以取到Config的配置。

 

3、測試經Zuul轉發的請求結果

例:一個request經gateway consumer producer走通,返回符合期望即可

此時你可以在gateway設置http端口轉發https、限制訪問方法(注冊EmbeddedServletContainerFactory、重寫addAdditionalTomcatConnectors)等。

看到com.netflix.zuul.exception.ZuulException: Forwarding error的報錯消失,至此在功能層面初步成功。

 

但是,https占用資源多些,考慮到性能應只讓gateway支持https,之后轉發http給springcloud client。網上看到了一些文章,實現應該不成問題。

然而這時我忽然想到,為什么不使用nginx支持https再轉發http給springcloud呢?springcloud不用動的,開發測試時也方便些。

待續。

 

注:

0、server和client當然可以配置不同的證書。

1、Lets Encrypt提供免費、自動生成的SSL證書,到期可自動更新。

2、使用 Lets Encrypt 生成用於 https 站點的免費 SSL 證書(集成nginx,尚未驗證)  參考https://lzw.me/a/lets-encrypt-ssl.html

3、若攻擊者有意,使用Fiddler作為中間人仍可以抓取https報文。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM