1. 使用 Spring Cloud Gateway
Srping Cloud Gateway需要Spring Boot和Spring Webflux提供的運行環境。不能運行在傳統的Servlet容器或者做為war包構建。
在項目中使用Spring Cloud Gateway,請使用帶有group為org.springframework.cloud和artifact為
spring-cloud-starter-gateway
的starter依賴。
有關使用當前的Spring Cloud發布系列設置構建系統的詳細信息,請參閱Spring Cloud Project page。
如果你包含了這個starter依賴,但是,由於某種原因,你不希望gateway被啟用,設置s
pring.cloud.gateway.enabled=false
。
2. 術語
Route(路由): 路由是網關的基本組件。它的定義是一個ID,一個目標URI,一組謂詞和一組過濾器。如果聚合謂詞為真,則匹配路由。
Predicate(謂詞): 這是一個 Java 8 Function Predicate.。輸入類型是一個 Spring Framework ServerWebExchange
.。這允許開發人員對HTTP請求中的任何內容進行匹配,例如頭和參數。
Filter(過濾器): 這些都是通過特定工程構建的Spring Framework GatewayFilter
的實例。在這里,可以在發送下游請求之前或之后修改請求和響應。
3. Spring Cloud Gateway的工作流程
客戶端向網關發送請求。如果網關處理映射的程序確定請求與路由匹配,它將被發送到網關Web處理程序。此處理程序通過特定於請求的過濾器鏈發送請求。
過濾器被虛線分隔的原因是過濾器可以在代理請求發送之前或之后執行邏輯。執行所有“pre”過濾邏輯,然后發出代理請求。在發出代理請求之后,將執行“post”過濾器邏輯。
4. 路由謂詞工廠
Spring Cloud Gateway將路由匹配為Spring WebFlux HandlerMapping基礎設施的一部分。Spring Cloud Gateway包括許多內置路由謂詞工廠。
所有的謂詞匹配HTTP請求的不同屬性。可以組合多個路由謂詞工廠,並通過邏輯進行組合。
4.1 After Route Predicate Factory
After Route Predicate Factory接收一個日期時間參數。這個謂詞匹配當前日期時間之后發生的請求。
譯者:id起一個標識的作用,並不是必須的,如果沒有id屬性,spring會生成一個uuid的id。
@NotEmpty private String id = UUID.randomUUID().toString();
application.yml.
spring:
cloud:
gateway:
routes:
- id: after_route
uri: http://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
這個路由匹配了時區為[America/Denver],2017年1月20號17:42:47之后的請求。如果當前請求的時間匹配,則會跳轉到uri的地址。
4.2 Before Route Predicate Factory
Before Route Predicate Factory接收一個日期時間參數。這個謂詞匹配當前日期時間之前發生的請求。
application.yml.
spring: cloud: gateway: routes: - id: before_route uri: http://example.org predicates: - Before=2019-01-20T17:42:47.789-07:00[America/Denver]
這個路由匹配了時區為[America/Denver],2019年1月20號17:42:47之前的請求。如果當前請求的時間匹配,則會跳轉到uri的地址。
4.3 Between Route Predicate Factory
Between Route Predicate Factory接收2個參數,datetime1和datetime2。這個謂詞匹配datetime1之后和datetime2之前發生的請求。datetime2參數必須在datetime1之后。
application.yml.
spring: cloud: gateway: routes: - id: between_route uri: http://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2019-01-21T17:42:47.789-07:00[America/Denver]
這個路由匹配了時區為[America/Denver],2017年1月20號17:42:47之后,2019年1月20號17:42:47之前的所有請求。這對維護windows很有用。
4.4 Cookie Route Predicate Factory
Cookie Route Predicate Factory 接收2個參數, cookie名稱和一個正則表達式。這個謂詞匹配具有給定名稱的cookie,而值匹配正則表達式。
spring: cloud: gateway: routes: - id: cookie_route uri: http://example.org predicates: - Cookie=chocolate, ch.p
這個路由匹配包含cookie名為chocolate,其值與ch.p正則表達式匹配的請求。
4.5 Header Route Predicate Factory
Header Route Predicate Factory接收2個參數,一個header中的名稱和一個正則表達式。這個謂詞與具有給定名稱的header,而值匹配正則表達式。
application.yml.
spring: cloud: gateway: routes: - id: header_route uri: http://example.org predicates: - Header=X-Request-Id, \d+
如果請求有一個名為X-Request-Id的header,其值與\d+正則表達式(值為一個或多個數字)匹配,則此路由將匹配。
4.6 Host Route Predicate Factory
Host Route Predicate Factory接收一個參數,主機名稱的模板。這個模板是一個ant分隔的模板,用.號作為分隔符。此謂詞匹配主機頭的模板。
application.yml.
spring: cloud: gateway: routes: - id: host_route uri: http://example.org predicates: - Host=**.somehost.org
如果請求有一個主機頭,其值為www.somehost.org或beta.somehost.org,則此路由將匹配。
4.7 Method Route Predicate Factory
Method Route Predicate Factory接收一個參數,HTTP請求的方法。
application.yml.
spring: cloud: gateway: routes: - id: method_route uri: http://example.org predicates: - Method=GET
如果是一個GET請求,這個路由將被匹配。
4.8 Path Route Predicate Factory
Path Route Predicate Factory接收一個參數,一個Spring PathMatcher
模板。
application.yml.
spring: cloud: gateway: routes: - id: host_route uri: http://example.org predicates: - Path=/foo/{segment}
如果請求路徑符合要求,則此路由將匹配,例如:/foo/1
或者 /foo/bar
。
該謂詞提取URI模板變量作為名稱和值的映射(就像上面例子中定義的segment),並將其放入ServerWebExchange.getAttributes()中,並在PathRoutePredicate.URL_PREDICATE_VARS_ATTR
中定義一個key。
然后,這些知可以供GatewayFilter Factories使用。
4.9 Query Route Predicate Factory
Query Route Predicate Factory 接收2個參數: 一個必須的參數和一個可選的表達式
。
application.yml.
spring: cloud: gateway: routes: - id: query_route uri: http://example.org predicates: - Query=baz
如果請求包含baz查詢參數,則此路由將匹配。
application.yml.
spring: cloud: gateway: routes: - id: query_route uri: http://example.org predicates: - Query=foo, ba.
如果請求包含一個foo查詢參數,其值與ba.匹配,則其路由將匹配。例如foo=bar和foo=baz。
4.10 RemoteAddr Route Predicate Factory
RemoteAddr Route Predicate Factory接受cidr符號(IPv4或IPv6)字符串的列表(最小大小為1),例如192.168.0.1/16(其中192.168.0.1是IP地址,16是子網掩碼)。
application.yml.
spring: cloud: gateway: routes: - id: remoteaddr_route uri: http://example.org predicates: - RemoteAddr=192.168.1.1/24
如果請求的遠程地址是192.168.1.10,則此路由將匹配。
4.10.1 修改遠程地址解析的方式
默認情況下,RemoteAddr Route Predicate Factory使用來自傳入請求的遠程地址。如果Spring Cloud網關位於代理層后面,這可能與實際客戶端IP地址不匹配。
您可以通過設置自定義RemoteAddressResolver
來定制解析遠程地址的方式。
Spring Cloud Gateway提供了一個非默認遠程地址解析器XForwardedRemoteAddressResolver,它基於x - forward - for報頭。
XForwardedRemoteAddressResolver有兩個靜態構造函數方法,采用不同的安全方法:
XForwardedRemoteAddressResolver::trustAll
返回一個RemoteAddressResolver,它總是取x - forward - for報頭中找到的第一個IP地址。
這種方法很容易被欺騙,因為惡意客戶端可以為x - forward設置一個初始值——解析器會接受這個初始值。
XForwardedRemoteAddressResolver::maxTrustedIndex
獲取與Spring Cloud Gateway前面運行的可信基礎結構數量相關的索引。
例如Spring Cloud Gateway,只能通過HAProxy訪問,那么應該使用1的值。如果在訪問Spring Cloud Gateway之前需要兩跳可信基礎設施,那么應該使用值2。
給定以下標題值:
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
下面的maxTrustedIndex值將產生以下遠程地址。
使用JAVA配置:
GatewayConfig.java
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver .maxTrustedIndex(1); ... .route("direct-route", r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24") .uri("https://downstream1") .route("proxied-route", r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24") .uri("https://downstream2") )