简单实现Zuul的请求过滤功能

我们知道在引入了Zuul作为Api网关服务后,它可以做到请求路由和负载均衡等功能,具体实现可以参考《zuul的简单实现》这篇博客


这时问题来了,难道我们要对所有的请求的进行正常的路由么,要是他是非法请求怎么办,这时我们就需要用到Zuul的请求过滤功能,根据我们自己的合法逻辑对经过Api服务网关的请求进行校验,决定是返回响应错误还是正常路由。

项目结构介绍:
在这里插入图片描述
从注册中心可以看到有3个服务实例:
API-GATEWAY
EUREKA-CLIENT
EUREKA-FEIGN-CLIENT

API-GATEWAY配置文件信息如下:

spring:
  application:
    name: api-gateway
server:
  port: 8766
zuul:
  routes:
     hello-feign:
                path: /hello-feign/**
                serviceId: eureka-feign-client
     hello-eureka:
                 path: /hello-eureka/**
                 serviceId: eureka-client
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

可以看到这里对 /hello-feign/** 和 /hello-eureka/**两个路径的请求配置了路由,采用的是服务路由。

另外两个服务的接口代码我就不贴了,直接描述下没加过滤器时的请求场景:
浏览器访问http://localhost:8766/hello-eureka/helloWorld/AA,这个请求时会经过Api网关Zuul的,结果如下:
在这里插入图片描述

接下里我们对Zuul的请求过滤功能做一个简单的实现,现在登陆一般都会校验token,所以就做一个token不为空,才正常路由的过滤功能。

一.写一个登陆过滤器LoginFilter,继承ZuulFilter类

package com.example.apigateway;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.ZuulFilterResult;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

public class LoginFilter extends ZuulFilter {
    public LoginFilter() {
        super();
    }

    @Override
    public boolean isStaticFilter() {
        return super.isStaticFilter();
    }

    @Override
    public String disablePropertyName() {
        return super.disablePropertyName();
    }

    @Override
    public boolean isFilterDisabled() {
        return super.isFilterDisabled();
    }

    @Override
    public ZuulFilterResult runFilter() {
        return super.runFilter();
    }

    @Override
    public int compareTo(ZuulFilter filter) {
        return super.compareTo(filter);
    }

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest httpServletRequest = requestContext.getRequest();
        Object token = httpServletRequest.getParameter("token");
        if (Objects.isNull(token)) {
            requestContext.setSendZuulResponse(false);
            //防止返回给前端时中文乱码
            requestContext.getResponse().setContentType("text/html;charset=UTF-8");
            requestContext.setResponseBody("当前状态未登录,请重新登录");
            requestContext.setResponseStatusCode(401);
            return null;
        }
        return null;
    }
}

从代码里可看出我们重写了filterType() ,filterOrder(),shouldFilter(),run()4个方法,这里解释下每个方法的作用:

filterType:这是过滤器的类型,决定过滤器在请求的那个生命周期会被执行,这里我设置成"pre",代表着过滤器在路由前执行。

filterOrder:过滤器的执行顺序,有时一个请求可能要执行多次过滤,这个方法值得返回值就决定了这过滤器的执行顺序,filterType相同的情况下,数字越小越先执行,负数也是一样。

shouldFilter:决定要不要执行过滤器,true则是要执行,false则是不要

run:过滤器执行的具体逻辑。 requestContext.setSendZuulResponse(false)这句很关键,设置成false后,会让Zuul过滤了该请求,不对这个请求进行路由。

二.加上过滤器配置类,启动时加载,让过滤器生效

@Configuration
public class Filter {
    @Bean
    public LoginFilter loginFilter() {
        return new LoginFilter();
    }
}

这时我们预想中的结果是,只要请求中没带token就会返回"当前状态未登录,请重新登录"

测试下试试:

浏览器访问http://localhost:8766/hello-eureka/helloWorld/AA,结果如下:
在这里插入图片描述
加上token参数后,浏览器访问http://localhost:8766/hello-eureka/helloWorld/AA?token=1,结果如下:
在这里插入图片描述
对请求成功过滤。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值