spring-cloud中zuul自定義service級別,api級別的路由白名單
一.service和api級別的路由
1.service級別的網關路由
public class ServiceIdWhiteTableRouteLocator extends DiscoveryClientRouteLocator { ... //主要重寫該方法,在調用完super的locateRoutes後再與白名單列表比較,提取出交集 @Override protected LinkedHashMap<String, ZuulProperties.ZuulRoute> locateRoutes() { LinkedHashMap<String, ZuulProperties.ZuulRoute> routeMaps = super.locateRoutes(); LinkedHashMap<String, ZuulProperties.ZuulRoute> whiteRouteMaps = new LinkedHashMap<>(); routeMaps.forEach((k, v) -> { if (PatternMatchUtils.simpleMatch(whites, v.getServiceId())) { whiteRouteMaps.put(k, v); } }); for (ZuulProperties.ZuulRoute route : this.properties.getRoutes().values()) { whiteRouteMaps.put(route.getPath(), route); } return whiteRouteMaps; } ... }
2.api級別的網關路由
public class PathWhiteTableHandleMapping extends ZuulHandlerMapping { ... //主要重寫該方法,在原有的ZuulHandlerMapping基礎上添加判斷是否在白名單的邏輯 @Override protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { if (this.errorController != null && urlPath.equals(this.errorController.getErrorPath())) { return null; } if (isIgnoredPath(urlPath, this.routeLocator.getIgnoredPaths())) return null; /** * 檢查是否在白名單中,不在白名單中的不路由 */ if (!isInPathWhiteTables(urlPath, this.pathWhites)) return null; RequestContext ctx = RequestContext.getCurrentContext(); if (ctx.containsKey("forward.to")) { return null; } if (this.dirty) { synchronized (this) { if (this.dirty) { registerHandlers(); this.dirty = false; } } } return super.lookupHandler(urlPath, request); } private boolean isInPathWhiteTables(String urlPath, Collection<String> pathWhites) { for (String whitePath : pathWhites) { if (this.pathMatcher.match(whitePath, urlPath)) { return true; } } return false; } public void setPathWhiteTables(Collection<String> whites) { this.pathWhites = whites; } ... }
二.config配置
1.首先卸載zuul自帶的auto config.
@SpringBootApplication(exclude = ZuulProxyAutoConfiguration.class)<br/>
2.需要全量copy三個類
org.springframework.cloud.netflix.zuul.RibbonCommandFactoryConfiguration
org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration
org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration
然後修改ZuulServerAutoConfiguration
中的zuulHandlerMapping的bean註冊:
@Bean(value = "discoveryRouteLocator")
public DiscoveryClientRouteLocator discoveryClientRouteLocator(ServerProperties server, DiscoveryClient discovery) {
//service白名單註入點
return new ServiceIdWhiteTableRouteLocator(server.getServlet().getServletPrefix(), discovery, this.zuulProperties, whiteRouteProperties.getWhiteServices());
}
@Bean(value = "zuulHandlerMapping")
public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) {
PathWhiteTableHandleMapping mapping = new PathWhiteTableHandleMapping(routes, zuulController());
mapping.setErrorController(this.errorController);
//路徑白名單註入點
mapping.setPathWhiteTables(whiteRouteProperties.getWhitePaths());
return mapping;
}
其中WhiteRouteProperties是一個裝載配置屬性的屬性類,自己定義即可。ZuulProxyAutoConfiguration
需要修改其父類為上述的ZuulServerAutoConfigurationn
。
三. 配置文件配置
主要是在application.yaml文件中增加:
zuul:
#控制service級別白名單(list)
white-services:
- ‘hello-server‘
#控制api級別白名單(list)
white-paths:
- ‘/hello/world‘
routes:
- url: hello-server
path: /hello/**
#默認全部不路由
ignored-services: ‘*‘
上述配置可以實現將/hello/**
該pattern請求路由到hello-server上,由於默認設置全部不路由,通過zuul.routes加進去(看源碼實現),然後由於設置了白名單功能,需要在white-services
上加上hello-server
,而white-paths
主要是控制白名單中的某個service中具體的哪個api可以被路由,如上可知是僅有/hello/world
可以被路由處理。
這樣就實現了多維度的白名單路由處理。
如有不足,請不吝賜教。
spring-cloud中zuul自定義service級別,api級別的路由白名單