通過配置網關白名單列表的方式,在過濾器中對白名單直接放行,可用於對外開放介面,內部系統的登錄後的攔截校驗等場景 ...
分享技術,用心生活
場景描述:一般系統中提供的介面都是經過統一配置鑒權的,比如不登錄不能訪問。但是,一些介面是需要開放給客戶用的,我稱作open API。那麼這時候你不能要求客戶先登錄你的介面再去調用吧。那麼,這時候就可以通過網關白名單來實現免鑒權
先說思路:
- 配置網關白名單列表
- 編寫鑒權過濾器
- 過濾器中讀取白名單
- 業務處理
簡單的時序圖
註: 如果使用的是網關過濾器,在校驗後應該再次過濾器,也就是經過2次;註意區別(網關過濾器具有前置pre、後置post兩次過濾,細節不在此處詳細探討)。
過濾器普遍用於處理攔截,校驗,改寫,日誌等場景;通過白名單來控制鑒權,正契合過濾器的作用。
1. 配置網關白名單
在你的本地的配置文件或者是nacos的配置文件中新增以下配置
可以配置url全路徑,也可以配置首碼路徑
gateway:
whitelist:
- /user/api/userInfo/query
- /open/oss/upload
- /open/vod/api
2. 過濾器配置
過濾器你可以選擇用spring的WebFilter
,如果你的系統集成了gateway也可以使用網關過濾器,然後自定義過濾器實現GlobalFilter
2.1. WebFilter實現
@Component
@RequiredArgsConstructor
public class AuthFilter implements WebFilter, Ordered {
private final GateWayProperties gateWayProperties;
private static final AntPathMatcher pathMatcher = new AntPathMatcher();
@Override
public int getOrder() {
return 1;
}
@Override
protected Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String urlMethod = request.getURI().getPath();
// 白名單匹配,直接放行
for (String pattern : gateWayProperties.getWhitelist()) {
if (pathMatcher.matchStart(pattern, urlMethod)) {
return chain.filter(exchange);
}
}
// 未匹配到
// 鑒權邏輯,此處省略....
}
}
2.2. 網關GlobalFilter實現
@Component
@RequiredArgsConstructor
public class AuthFilter implements GlobalFilter, Ordered {
private final GateWayProperties gateWayProperties;
private static final AntPathMatcher pathMatcher = new AntPathMatcher();
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String urlMethod = request.getURI().getPath();
// 白名單匹配,直接放行
for (String pattern : gateWayProperties.getWhitelist()) {
if (pathMatcher.matchStart(pattern, urlMethod)) {
return chain.filter(exchange);
}
}
// 未匹配到,忽略鑒權邏輯,直接設置401
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
@Override
public int getOrder() {
return 0;
}
}
2.3. 讀取白名單配置
GateWayProperties
中的prefix和配置文件中的名稱一致
@Getter
@Setter
@ToString
@ConfigurationProperties(prefix = "gateway")
public class GateWayProperties implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> whitelist;
}
3. 演示效果
使用上面配置的查詢用戶信息介面/user/api/userInfo/query
做演示
3.1. 在白名單內
WebFilter
效果
查看斷點gateWayProperties
中白名單列表已獲取到,且比對結果為true
GlobalFilter
效果
查看斷點gateWayProperties
中白名單列表也已獲取到,且比對結果為true
查詢結果:已獲取到用戶信息
3.2. 不在白名單內
我們把介面/user/api/userInfo/query
從白名單中刪除,用網關過濾器演示。
查看斷點gateWayProperties
中白名單列表已沒有查詢用戶介面,且返回了401
查詢結果:http狀態碼是我們設置的401
當然,使用白名單也不僅僅局限於對外開放介面這個場景,也不僅僅局限於使用在鑒權過濾器上。這裡只是一個拋磚引玉。實際需求可以結合自己的業務場景,使用不同的過濾器。