找回密码
 立即注册
首页 业界区 业界 巧用网关白名单实现接口免鉴权

巧用网关白名单实现接口免鉴权

洫伍俟 前天 20:07
分享技术,用心生活

场景描述:一般系统中提供的接口都是经过统一配置鉴权的,比如不登录不能访问。但是,一些接口是需要开放给客户用的,我称作open API。那么这时候你不能要求客户先登录你的接口再去调用吧。那么,这时候就可以通过网关白名单来实现免鉴权
先说思路:

  • 配置网关白名单列表
  • 编写鉴权过滤器
  • 过滤器中读取白名单
  • 业务处理
简单的时序图
1.png

注: 如果使用的是网关过滤器,在校验后应该再次过滤器,也就是经过2次;注意区别(网关过滤器具有前置pre、后置post两次过滤,细节不在此处详细探讨)。
过滤器普遍用于处理拦截,校验,改写,日志等场景;通过白名单来控制鉴权,正契合过滤器的作用。
1. 配置网关白名单

在你的本地的配置文件或者是nacos的配置文件中新增以下配置
可以配置url全路径,也可以配置前缀路径
  1. gateway:
  2.   whitelist:
  3.     - /user/api/userInfo/query
  4.     - /open/oss/upload
  5.     - /open/vod/api
复制代码
2. 过滤器配置

过滤器你可以选择用spring的WebFilter,如果你的系统集成了gateway也可以使用网关过滤器,然后自定义过滤器实现GlobalFilter
2.1. WebFilter实现
  1. @Component
  2. @RequiredArgsConstructor
  3. public class AuthFilter implements WebFilter, Ordered {
  4.     private final GateWayProperties gateWayProperties;
  5.     private static final AntPathMatcher pathMatcher = new AntPathMatcher();
  6.     @Override
  7.     public int getOrder() {
  8.         return 1;
  9.     }
  10.     @Override
  11.     protected Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
  12.         ServerHttpRequest request = exchange.getRequest();
  13.         String urlMethod = request.getURI().getPath();
  14.         // 白名单匹配,直接放行
  15.         for (String pattern : gateWayProperties.getWhitelist()) {
  16.             if (pathMatcher.matchStart(pattern, urlMethod)) {
  17.                 return chain.filter(exchange);
  18.             }
  19.         }
  20.        // 未匹配到
  21.        // 鉴权逻辑,此处省略....
  22.     }
  23. }
复制代码
2.2. 网关GlobalFilter实现
  1. @Component
  2. @RequiredArgsConstructor
  3. public class AuthFilter implements GlobalFilter, Ordered {
  4.     private final GateWayProperties gateWayProperties;
  5.     private static final AntPathMatcher pathMatcher = new AntPathMatcher();
  6.     @Override
  7.     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  8.         ServerHttpRequest request = exchange.getRequest();
  9.         String urlMethod = request.getURI().getPath();
  10.         // 白名单匹配,直接放行
  11.         for (String pattern : gateWayProperties.getWhitelist()) {
  12.             if (pathMatcher.matchStart(pattern, urlMethod)) {
  13.                 return chain.filter(exchange);
  14.             }
  15.         }
  16.         // 未匹配到,忽略鉴权逻辑,直接设置401
  17.         exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
  18.         return exchange.getResponse().setComplete();
  19.     }
  20.     @Override
  21.     public int getOrder() {
  22.         return 0;
  23.     }
  24. }
复制代码
2.3. 读取白名单配置

GateWayProperties中的prefix和配置文件中的名称一致
  1. @Getter
  2. @Setter
  3. @ToString
  4. @ConfigurationProperties(prefix = "gateway")
  5. public class GateWayProperties implements Serializable {
  6.     private static final long serialVersionUID = 1L;
  7.     private List<String> whitelist;
  8. }
复制代码
3. 演示效果

使用上面配置的查询用户信息接口/user/api/userInfo/query做演示
3.1. 在白名单内


  • WebFilter效果
查看断点gateWayProperties中白名单列表已获取到,且比对结果为true
2.png


  • GlobalFilter效果
查看断点gateWayProperties中白名单列表也已获取到,且比对结果为true
3.png

查询结果:已获取到用户信息
4.png

3.2. 不在白名单内

我们把接口/user/api/userInfo/query从白名单中删除,用网关过滤器演示。
查看断点gateWayProperties中白名单列表已没有查询用户接口,且返回了401
5.png

查询结果:http状态码是我们设置的401
6.png

当然,使用白名单也不仅仅局限于对外开放接口这个场景,也不仅仅局限于使用在鉴权过滤器上。这里只是一个抛砖引玉。实际需求可以结合自己的业务场景,使用不同的过滤器。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册