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

举报
yd_245700808 发表于 2023/09/09 15:36:17 2023/09/09
【摘要】 分享技术,用心生活场景描述:一般系统中提供的接口都是经过统一配置鉴权的,比如不登录不能访问。但是,一些接口是需要开放给客户用的,我称作open API。那么这时候你不能要求客户先登录你的接口再去调用吧。那么,这时候就可以通过网关白名单来实现免鉴权先说思路:配置网关白名单列表编写鉴权过滤器过滤器中读取白名单业务处理简单的时序图用户过滤器业务系统发起请求校验白名单通过不通过success用户过滤...

分享技术,用心生活

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

先说思路:

  1. 配置网关白名单列表
  2. 编写鉴权过滤器
  3. 过滤器中读取白名单
  4. 业务处理

简单的时序图

用户过滤器业务系统发起请求校验白名单通过不通过success用户过滤器业务系统

注: 如果使用的是网关过滤器,在校验后应该再次过滤器,也就是经过2次;注意区别(网关过滤器具有前置pre、后置post两次过滤,细节不在此处详细探讨)。

过滤器普遍用于处理拦截,校验,改写,日志等场景;通过白名单来控制鉴权,正契合过滤器的作用。

1. 配置网关白名单

在你的本地的配置文件或者是nacos的配置文件中新增以下配置

可以配置url全路径,也可以配置前缀路径

yml复制代码gateway:
  whitelist:
    - /user/api/userInfo/query
    - /open/oss/upload
    - /open/vod/api

2. 过滤器配置

过滤器你可以选择用spring的WebFilter,如果你的系统集成了gateway也可以使用网关过滤器,然后自定义过滤器实现GlobalFilter

2.1. WebFilter实现

java复制代码@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实现

java复制代码@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要和配置文件中的名称保持一致

java复制代码@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://juejin.cn/post/7260506612971683896

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。