Gateway 网关 (四) GatewayFilterFactory 局部过滤器 权限校验

 废话

业务多,逻辑复杂的情况下,可能不同的域名过来的请求、不同的路径就需要配置不同的权限校验方式,这种情况的话直接用全局过滤器似乎就不是很方便了。

用这种方式的话确实会比较灵活,但是……老实说业务太复杂了也是配置文件挺大的,条件也多。

所以这里采用了一个专门用来做权限校验的局部过滤器(也可实现其他业务逻辑),搭配nacos动态配置,基本上可以满足业务需求。

缺点,gateway搭配nacos只能是用json的形式(yml理论上也可以,但是需要写的处理逻辑就太多了,麻烦),而nacos中json和yml只能是用一种方式,所以用了json之后,其他的参数就不能很简单的就实现动态配置了。(如果有比较方便的方法,请告诉我)

gateway搭配nacos使用的赘述了,具体翻我之前的文章:Gateway 网关 (一) Nacos 动态配置路由

开搞

如果是直接新建一个原始的局部过滤器GatewayFilter的话,调用的方式有点麻烦,且无法动态变更,所以用GatewayFilterFactory。

大概流程就是定义一个Config参数配置类(可以按需配置,多参数啥的都是可以的),然后重写GatewayFilterFactory类,过滤逻辑就写在重写的这个类里面。

然后在nacos的json配置里面加上对应的配置逻辑就可以生效了

新建一个AuthorizeGatewayFilterFactory类,继承GatewayFilterFactory,并在内部新建一个Config配置类


@Component//切记这个不要漏,漏了这个搞得我出错了半天还怀疑人生
public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {


    /**
     * 不设防
     */
    private static final String AUTH_NOT = "not";
    /**
     * 静态资源文件
     */
    private static final String AUTH_STATIC = "static";
    /**
     * 网页端
     */
    private static final String AUTH_WEB = "web";
    /**
     * 中台
     */
    private static final String AUTH_BACK = "back";
    /**
     * 埋点
     */
    private static final String AUTH_DOT = "dot";
    /**
     * 客户端接口
     */
    private static final String AUTH_API = "api";
    /**
     * api接口加密
     */
    private static final String AUTH_API_EN = "apien";


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public AuthorizeGatewayFilterFactory() {
        super(Config.class);
        ALog.info(LogEnum.CUSTOM_FILTER.getTag(), "Loaded GatewayFilterFactory [Authorize]");
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("type");
    }

    @Override
    public GatewayFilter apply(AuthorizeGatewayFilterFactory.Config config) {
        return (exchange, chain) -> {
            if (config.getType().equals(AUTH_API)) {
                //api已登录
                DataBuffer buffer = exchange.getResponse().bufferFactory().wrap("{\"code\":10011,\"msg\":\"权限校验不通过\"}".getBytes(StandardCharsets.UTF_8));
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                exchange.getResponse().getHeaders().add("Content-Type", "application/json;charset=UTF-8");
                return exchange.getResponse().writeWith(Mono.just(buffer));
            }

            if (config.getType().equals(AUTH_NOT)) {
                //不设防
                return chain.filter(exchange);
            }
            if (config.getType().equals(AUTH_API_EN)) {
                //API接口加密
                return chain.filter(exchange);
            }
            if (config.getType().equals(AUTH_API_NOT)) {
                //API未登录
                return chain.filter(exchange);
            }
            if (config.getType().equals(AUTH_STATIC)) {
                //静态资源文件
                return chain.filter(exchange);
            }
            if (config.getType().equals(AUTH_WEB)) {
                //网页端
                return chain.filter(exchange);
            }
            if (config.getType().equals(AUTH_BACK)) {
                //中台
                return chain.filter(exchange);
            }

            if (config.getType().equals(AUTH_DOT)) {
                //埋点
                return chain.filter(exchange);
            }

            DataBuffer buffer = exchange.getResponse().bufferFactory().wrap("{\"code\":10086,\"msg\":\"请配置权限\"}".getBytes(StandardCharsets.UTF_8));
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            exchange.getResponse().getHeaders().add("Content-Type", "application/json;charset=UTF-8");
            return exchange.getResponse().writeWith(Mono.just(buffer));
        };
    }


    @Getter
    @Setter
    public static class Config {
        /**
         * 过滤类型:not-不设防(正常玩野),web-网页端,api-前端(),api-not-前端未登录,static-静态/资源文件(css样式表等),back-中台,dot-埋点
         */
        private String type;

    }

nacos配置

[
    {
        "id":"test-service",//路由id,单条不要重复
        "order":10,//优先级,数字越大优先级越低
        "predicates":[
            {
                "args":{
                    "pattern":"/email/**",
                    "pattern1":"/ttt/**"
                },
                "name":"Path"//监听路径
            },
            {
                "args":{
                    "pattern":"aaa.nnn**",
                    "pattern1":"ccc.nnn**",
                    "pattern2":"localhost**"
                },
                "name":"Host"//指定符合规则的域名
            }
        ],
        "filters":[
            {
                "args":{
                    "_genkey_0":"1"//转发之后去除一个前缀(按需设置),如/email/test转发之后变成/test
                },
                "name":"StripPrefix"//去除uri前缀
            },
            {
                "args":{
                    "_genkey_0":"/api"
                },
                "name":"PrefixPath"//转发之后新增前缀,如/test转发之后变成/api/test
            },
            {
                "args":{
                    "type":"api"//过滤器里面congif类的值,type跟config里面的字段名称一致,如果有多个配置就写在这里
                },
                "name":"Authorize"//自定义过滤器AuthorizeGatewayFilterFactory(根据类名去掉GatewayFilterFactory的值,无需配置)
            }
        ],
        "uri":"http://192.168.2.200:10201/"//转发之后路径
    }
]

依照上面的规则(前提是中间的权限校验能过)

转发之前的路径:
http://localhost:10100/email/aaa

转发之后的路径:
http://192.168.2.200:10201/api/aaa

最终结果

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值