分享技术,用心生活
❝
场景描述:一般系统中提供的接口都是经过统一配置鉴权的,比如不登录不能访问。但是,一些接口是需要开放给客户用的,我称作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

当然,使用白名单也不仅仅局限于对外开放接口这个场景,也不仅仅局限于使用在鉴权过滤器上。这里只是一个抛砖引玉。实际需求可以结合自己的业务场景,使用不同的过滤器。
原文始发于微信公众号(指南针技术):巧用网关白名单实现接口免鉴权
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/230351.html