(四)啟用HTTPS


  安全規范中有一條是要求盡量使用https而棄用http(新Chrome將標記非HTTPS網站為不安全),其實啟用https和之前的ipv6改造一樣,並不是什么高難度或者工作流繁多的的改造,只需將中間件啟用https支持即可。在spring boot項目中,基本上都是使用內置的中間件(tomcat、netty等),下面記錄下改造的思路:

方案1: 服務均啟用https,步驟有:

  1. 所有的micro service均啟用https
  2. 把eureka的注冊地址改為https方式
  3. 把config service的注冊地址改為https方式
  4. 把feign的調用方式改為支持https方式
  5. 每個micro service均需導入證書,並且訪問的時候需要導入證書(不然會報unable to find valid certification path to requested target錯誤)
  6. 證書里需要把micro service的serviceId注冊進去(不然會報Certificate doesn't match any of the subject alternative names錯誤)

方案比較穩妥,所有服務中均走了ssl,滿足安全條件,就是乍一看改造量有點多啊......

方案2:micro service只會暴露gateway,其余服務均是不暴露的,因此我們可以只改造gateway服務,步驟有:

  1. gateway service啟用https
  2. gateway service改造lb://micro_service_id的地址替換方式

該方案改造量最小,且由於spring cloud的服務隔離的關系,並無需擔心其余服務的安全問題。


 

實現方案:

  1. 生成證書

  可以用JDK自帶的keytool工具,來生成證書,具體語法為:

C:\Users\Administrator>keytool
密鑰和證書管理工具

命令:

 -certreq            生成證書請求
 -changealias        更改條目的別名
 -delete             刪除條目
 -exportcert         導出證書
 -genkeypair         生成密鑰對
 -genseckey          生成密鑰
 -gencert            根據證書請求生成證書
 -importcert         導入證書或證書鏈
 -importpass         導入口令
 -importkeystore     從其他密鑰庫導入一個或所有條目
 -keypasswd          更改條目的密鑰口令
 -list               列出密鑰庫中的條目
 -printcert          打印證書內容
 -printcertreq       打印證書請求的內容
 -printcrl           打印 CRL 文件的內容
 -storepasswd        更改密鑰庫的存儲口令

使用 "keytool -command_name -help" 獲取 command_name 的用法

  生成證書的語句為:

keytool -genkeypair -alias "ncdt" -keyalg "RSA" -keystore "C:\ncdt.keystore"

  執行后,根據提示完成即可(測試用的話,直接一直按回車,最后確認y即可),如下圖:

  2. spring cloud gateway項目啟用https(其實也就是spring boot項目啟用https),只需要在application.yml里增加ssl配置即可。

server:
  port: 443
  ssl:
    key-alias: ncdt
    enabled: true
    key-store-password: password
    key-store-type: JKS
    key-store: ncdt.keystore

  3.spring cloud gateway項目增加HttpsReconstructFilter

  如何來重寫這個filter呢,首先先不要寫這個filter,直接啟動gateway並訪問地址:https://localhost/,就會報如下錯誤(里面的*****是我自己的服務名,故隱藏了):

2018-09-19 11:19:26.420  INFO 10808 --- [ctor-http-nio-1] c.netflix.loadbalancer.BaseLoadBalancer  : Client: ***** instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=*****,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2018-09-19 11:19:26.424  INFO 10808 --- [ctor-http-nio-1] c.n.l.DynamicServerListLoadBalancer      : Using serverListUpdater PollingServerListUpdater
2018-09-19 11:19:26.427  INFO 10808 --- [ctor-http-nio-1] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client ***** initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=*****,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@7b98208b
2018-09-19 11:19:26.490 ERROR 10808 --- [ctor-http-nio-1] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request [GET https://localhost/******]

org.springframework.cloud.gateway.support.NotFoundException: Unable to find instance for *****
    at org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.filter(LoadBalancerClientFilter.java:72) ~[spring-cloud-gateway-core-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.cloud.gateway.handler.FilteringWebHandler$GatewayFilterAdapter.filter(FilteringWebHandler.java:133) ~[spring-cloud-gateway-core-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.cloud.gateway.filter.OrderedGatewayFilter.filter(OrderedGatewayFilter.java:44) ~[spring-cloud-gateway-core-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.lambda$filter$0(FilteringWebHandler.java:115) ~[spring-cloud-gateway-core-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:45) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:271) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:803) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1083) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:144) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:271) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:803) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:73) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:185) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1083) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFilterWhen$MonoFilterWhenMain.onNext(MonoFilterWhen.java:138) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1640) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFilterWhen$MonoFilterWhenMain.onSubscribe(MonoFilterWhen.java:103) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFilterWhen.subscribe(MonoFilterWhen.java:56) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoPeek.subscribe(MonoPeek.java:71) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:418) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:241) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.onNext(FluxDematerialize.java:114) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.onNext(FluxDematerialize.java:42) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:244) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:202) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.request(FluxDematerialize.java:157) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:227) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.onSubscribe(FluxDematerialize.java:88) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:140) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:64) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxDematerialize.subscribe(FluxDematerialize.java:39) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:55) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoNext.subscribe(MonoNext.java:40) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoMap.subscribe(MonoMap.java:55) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoMap.subscribe(MonoMap.java:55) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:418) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:210) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:140) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:64) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoNext.subscribe(MonoNext.java:40) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1083) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoZip$ZipCoordinator.signal(MonoZip.java:247) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoZip$ZipInner.onNext(MonoZip.java:329) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1640) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoZip$ZipInner.onSubscribe(MonoZip.java:318) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoZip.subscribe(MonoZip.java:128) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:70) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) ~[reactor-core-3.1.8.RELEASE.jar:3.1.8.RELEASE]
    at reactor.ipc.netty.channel.ChannelOperations.applyHandler(ChannelOperations.java:380) ~[reactor-netty-0.7.8.RELEASE.jar:0.7.8.RELEASE]
    at reactor.ipc.netty.http.server.HttpServerOperations.onHandlerStart(HttpServerOperations.java:398) ~[reactor-netty-0.7.8.RELEASE.jar:0.7.8.RELEASE]
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:163) ~[netty-common-4.1.27.Final.jar:4.1.27.Final]
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java) ~[netty-common-4.1.27.Final.jar:4.1.27.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) ~[netty-common-4.1.27.Final.jar:4.1.27.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:464) ~[netty-transport-4.1.27.Final.jar:4.1.27.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) ~[netty-common-4.1.27.Final.jar:4.1.27.Final]
    at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_77]
View Code

  可以看到里面調用的是ribbonloadbalancer,因此我們可以直接看gateway里的全局過濾器接口GlobalFilter,找這個接口的所有實現類:

  找到LoadBalancerClientFilter,可以看到這個filter調用了loadBalancer.reconstructURI(new DelegatingServiceInstance(instance, overrideScheme), uri),並重新寫入到GATEWAY_REQUEST_URL_ATTR中。

  在繼續往下找(代碼不難),最終會看到這個filter是執行了RibbonUtils的一個私有方法upgradeConnection,功能是:如果調用的服務要求安全的,就判斷原始uri的scheme是否是http,是則轉化為https,否則就按照原始請求的。

  那么我們的要求是gateway為https,轉發后的uri依然保持http不變,與上功能相反,因此我們可以仿造LoadBalancerClientFilter,並重寫RibbonUtilsupgradeConnection方法,調整filter的執行順序,由於不是升級連接,因此重命名了一下,代碼如下:

/**
 * @author zhangqiuyang
 * Created on 2018/6/9.
 */
@Configuration
public class HttpsReconstructFilter implements GlobalFilter, Ordered {
private static final int HTTPS_RECONSTRUCT_FILTER_ORDER = 10101; /** * Process the Web request and (optionally) delegate to the next * {@code WebFilter} through the given {@link GatewayFilterChain}. * * @param exchange the current server exchange * @param chain provides a way to delegate to the next filter * @return {@code Mono<Void>} to indicate when request processing is complete */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); if (url != null && "https".equals(url.getScheme())) { exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, reconstructURIConnection(url)); } return chain.filter(exchange); } /** * 重構url,把https修改為http * * @param uri * @return
     */
    private static URI reconstructURIConnection(URI uri) { UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUri(uri).scheme("http"); if (uri.getRawQuery() != null) { // When building the URI, UriComponentsBuilder verify the allowed characters and does not // support the '+' so we replace it for its equivalent '%20'. // See issue https://jira.spring.io/browse/SPR-10172
            uriComponentsBuilder.replaceQuery(uri.getRawQuery().replace("+", "%20")); } return uriComponentsBuilder.build(true).toUri(); } /** * Get the order value of this object. * <p>Higher values are interpreted as lower priority. As a consequence, * the object with the lowest value has the highest priority (somewhat * analogous to Servlet {@code load-on-startup} values). * <p>Same order values will result in arbitrary sort positions for the * affected objects. * * @return the order value * @see #HIGHEST_PRECEDENCE * @see #LOWEST_PRECEDENCE */ @Override public int getOrder() { return HTTPS_RECONSTRUCT_FILTER_ORDER; } }

改造就完成了,重啟服務后訪問,就可以看到效果。

生產環境證書:

  許多生產環境的證書都是從godaddy(參考官方幫助)或者其他網站上申請的,得到的是一個gd_bundle開頭的.crt證書和一個隨機名稱.crt證書,那這時如果要在spring boot上用這個證書,則需要進行一下轉換,把證書轉換成jks證書

openssl pkcs12 -export -in 隨機名稱證書.crt -inkey 私鑰.key -out ncdt.p12 -name tomcat -CAfile gd_bundle開頭證書.crt -caname root -chain

  執行完會要求輸入密碼,自己指定即可。

keytool -importkeystore -destkeystore ncdt.jks -srckeystore ncdt.p12 -srcstoretype PKCS12

  執行完再次輸入密碼,生成.jks文件。

同時,spring boot的ssl配置應該為:

server:
  port: 443
  ssl:
    enabled: true
    key-store-password: 密碼
    key-store: ncdt.jks

重啟完成配置。

 


免責聲明!

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



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