在前两篇文章:服务网关(基础)、服务网关(路由配置)中,我们了解了Spring Cloud Zuul作为网关所具备的最基本功能:路由。本文我们将具体介绍一下Spring Cloud Zuul的另一项核心功能:过滤器。

过滤器的作用

通过上面所述的两篇我们,我们已经能够实现请求的路由功能,所以我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了。但是,每个客户端用户请求微服务应用提供的接口时,它们的访问权限往往都需要有一定的限制,系统并不会将所有的微服务接口都对它们开放。然而,目前的服务路由并没有限制权限这样的功能,所有请求都会被毫无保留地转发到具体的应用并返回结果,为了实现对客户端请求的安全校验和权限控制,最简单和粗暴的方法就是为每个微服务应用都实现一套用于校验签名和鉴别权限的过滤器或拦截器。不过,这样的做法并不可取,它会增加日后的系统维护难度,因为同一个系统中的各种校验逻辑很多情况下都是大致相同或类似的,这样的实现方式会使得相似的校验逻辑代码被分散到了各个微服务中去,冗余代码的出现是我们不希望看到的。所以,比较好的做法是将这些校验逻辑剥离出去,构建出一个独立的鉴权服务。在完成了剥离之后,有不少开发者会直接在微服务应用中通过调用鉴权服务来实现校验,但是这样的做法仅仅只是解决了鉴权逻辑的分离,并没有在本质上将这部分不属于业余的逻辑拆分出原有的微服务应用,冗余的拦截器或过滤器依然会存在。

对于这样的问题,更好的做法是通过前置的网关服务来完成这些非业务性质的校验。由于网关服务的加入,外部客户端访问我们的系统已经有了统一入口,既然这些校验与具体业务无关,那何不在请求到达的时候就完成校验和过滤,而不是转发后再过滤而导致更长的请求延迟。同时,通过在网关中完成校验和过滤,微服务应用端就可以去除各种复杂的过滤器和拦截器了,这使得微服务应用的接口开发和测试复杂度也得到了相应的降低。

为了在API网关中实现对客户端请求的校验,我们将需要使用到Spring Cloud Zuul的另外一个核心功能:过滤器

Zuul允许开发者在API网关上通过定义过滤器来实现对请求的拦截与过滤,实现的方法非常简单,我们只需要继承ZuulFilter抽象类并实现它定义的四个抽象函数就可以完成对请求的拦截和过滤了。

过滤器的实现

比如下面的代码,我们定义了一个简单的Zuul过滤器,它实现了在请求被路由之前检查HttpServletRequest中是否有accessToken参数,若有就进行路由,若没有就拒绝访问,返回401 Unauthorized错误。

public class AccessFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);

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

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

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

    @Override    public Object run() {        RequestContext ctx = RequestContext.getCurrentContext();        HttpServletRequest request = ctx.getRequest();

         log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());

        Object accessToken = request.getParameter("accessToken");        if(accessToken == null) {            log.warn("access token is empty");            ctx.setSendZuulResponse(false);            ctx.setResponseStatusCode(401);            return null;        }        log.info("access token ok");        return null;    }

}

在上面实现的过滤器代码中,我们通过继承ZuulFilter抽象类并重写了下面的四个方法来实现自定义的过滤器。这四个方法分别定义了:

  • filterType:过滤器的类型,它决定过滤器在请求的哪个生命周期中执行。这里定义为pre,代表会在请求被路由之前执行。
  • filterOrder:过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行。
  • shouldFilter:判断该过滤器是否需要被执行。这里我们直接返回了true,因此该过滤器对所有请求都会生效。实际运用中我们可以利用该函数来指定过滤器的有效范围。
  • run:过滤器的具体逻辑。这里我们通过ctx.setSendZuulResponse(false)令zuul过滤该请求,不对其进行路由,然后通过ctx.setResponseStatusCode(401)设置了其返回的错误码,当然我们也可以进一步优化我们的返回,比如,通过ctx.setResponseBody(body)对返回body内容进行编辑等。

在实现了自定义过滤器之后,它并不会直接生效,我们还需要为其创建具体的Bean才能启动该过滤器,比如,在应用主类中增加如下内容:

@EnableZuulProxy@SpringCloudApplicationpublic class Application {

  public static void main(String[] args) {      new SpringApplicationBuilder(Application.class).web(true).run(args);  }

   @Bean    public AccessFilter accessFilter() {      return new AccessFilter();    }}

在对api-gateway服务完成了上面的改造之后,我们可以重新启动它,并发起下面的请求,对上面定义的过滤器做一个验证:

  • http://localhost:1101/api-a/hello:返回401错误
  • http://localhost:1101/api-a/hello&accessToken=token:正确路由到hello-service/hello接口,并返回Hello World

到这里,对于Spring Cloud Zuul过滤器的基本功能就以介绍完毕。读者可以根据自己的需要在服务网关上定义一些与业务无关的通用逻辑实现对请求的过滤和拦截,比如:签名校验、权限校验、请求限流等功能。

进阶阅读

为了更好的理解和扩展Spring Cloud Zuul,我们可以阅读下面这些文章,有助于深入的了解其内部运行机制,以指导我们合理的编写过滤器逻辑:

  • Spring Cloud源码分析(四)Zuul:核心过滤器
  • Spring Cloud实战小贴士:Zuul处理Cookie和重定向
  • Spring Cloud实战小贴士:Zuul统一异常处理(一)
  • Spring Cloud实战小贴士:Zuul统一异常处理(二)
  • Spring Cloud实战小贴士:Zuul统一异常处理(三)【Dalston版】

Spring Cloud构建微服务架构:服务网关(过滤器)【Dalston版】相关推荐

  1. Spring Cloud构建微服务架构(五)服务网关

    通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: alt 我们使用Spring Cloud Netflix中的Eureka实 ...

  2. Spring Cloud构建微服务架构:服务网关(路由配置)【Dalston版】

    在上一篇<Spring Cloud构建微服务架构:服务网关(基础)>一文中,我们通过使用Spring Cloud Zuul构建了一个基础的API网关服务,同时也演示了Spring Clou ...

  3. Spring Cloud构建微服务架构:分布式服务跟踪(整合zipkin)【Dalston版】

    通过上一篇<分布式服务跟踪(整合logstash)>,我们虽然已经能够利用ELK平台提供的收集.存储.搜索等强大功能,对跟踪信息的管理和使用已经变得非常便利.但是,在ELK平台中的数据分析 ...

  4. Spring Cloud构建微服务架构:分布式服务跟踪(整合logstash)【Dalston版】

    通过之前的<入门示例>,我们已经为两个由SpringCloud构建的微服务项目 trace-1和 trace-2引入了Spring Cloud Sleuth的基础模块 spring-clo ...

  5. Spring Cloud构建微服务架构:分布式服务跟踪(跟踪原理)

    通过上一篇<分布式服务跟踪(入门)>的例子,我们已经通过Spring Cloud Sleuth往微服务应用中添加了实现分布式跟踪具备的基本要素.下面通过本文来详细说说实现分布式服务跟踪的一 ...

  6. Spring Cloud构建微服务架构:服务容错保护(Hystrix断路器)

    断路器 断路器模式源于Martin Fowler的Circuit Breaker一文."断路器"本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时," ...

  7. Spring Cloud构建微服务架构(七)消息总线(续:Kafka)

    Spring Cloud Bus除了支持RabbitMQ的自动化配置之外,还支持现在被广泛应用的Kafka.在本文中,我们将搭建一个Kafka的本地环境,并通过它来尝试使用Spring Cloud B ...

  8. Spring Cloud构建微服务架构:分布式配置中心【Dalston版】

    Spring Cloud Config是Spring Cloud团队创建的一个全新项目,用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端与客户端两个部分.其中服务端也称为 ...

  9. Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)【Dalston版】

    前言 在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与订阅的方式互相依赖.由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服 ...

  10. Spring Cloud构建微服务架构:服务容错保护(Hystrix依赖隔离)【Dalston版】

    前言 在上一篇<Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)>中,我们已经体验了如何使用@HystrixCommand来为一个依赖资源定义服务降级逻辑.实 ...

最新文章

  1. 「SAP技术」SAP MM 采购信息记录新价格不能体现在采购订单新的ITEM上?
  2. 如何在JavaScript中反转字符串?
  3. ant design pro(一)安装、目录结构、项目加载启动【原始、以及idea开发】
  4. Careercup - Google面试题 - 5424071030341632
  5. vb.net 2019-机器学习ml.net情绪分析(3)
  6. sqlserver安装检测不通过 (重新启动失败)
  7. .net身份证号码验证
  8. java 发送邮件昵称_javaMail发送邮件设置发件人中文昵称
  9. mysql fetch rows,php中mysql_fetch_array()和mysql_fetch_rows()函数区别
  10. error40;无法打开到SQL Server的连接,设置了Tcp/IP等也不能连接的问题
  11. java mvc controller_java之spring mvc之Controller配置的几种方式
  12. HTML:在HTML前端界面中直接显示代码
  13. 在Linux下使用GIMP打印一寸照
  14. 多元函数的极限、连续
  15. 罗技无法使用计算机上的配置文件,罗技无线鼠标接收器无法配对的详细解决办法...
  16. win10网络适配器不见了_恢复消失的win10网络适配器的方法
  17. 起步 —— 种一棵树最好的时间是十年前
  18. 悦诗风吟网络营销的目标_悦诗风吟七彩泥膜术线上推广方案
  19. ae正在发生崩溃_AE崩溃了怎么办?这可能是最全面的解决办法了!
  20. AndroidStudio - - - 点击头像更换头像_菜单选择_相机拍照与相册获取

热门文章

  1. LeetCode OJ - Valid Palindrome
  2. (译)Windows Azure的7月更新:SQL数据库,流量管理,自动缩放,虚拟机
  3. Linux驱动程序的数据封装
  4. container_of实例
  5. Android 异常问题分析
  6. MDK调试:设置断点处,代码运行的次数
  7. Cortex M3 NVIC与中断控制
  8. android 4.4 下拉菜单 透明,4.2状态栏,下拉,全局透明教程
  9. php 动态参数,php怎么实现动态传参数?
  10. word图片嵌入式为何只能看到一部分_Word排版的正确姿势!(Word论文排版教学)...