每个客户端用户请求微服务应用提供的接口时,它们权限往往都有一定的限制,系统并不会将所有的微服务接口都对它们开放。然而服务路由并没有限制权限这样的功能,所有请求被毫无保留的转发到具体应用并返回结果,为了实现对客户端请求的安全校验签名和权限控制,最简单和粗暴的方法就是为每个微服务应用都实现一套用于校验签名和鉴别权限的的过滤器或拦截器。不过这样会增加日后的维护难度,而且代码也变得冗余。所以最好的做法是将这些检验剥离出去,构建一个独立的鉴权服务。
那么更好的做法是通过前置的网关服务来完成这些非业务性质的校验。由于网关服务的加入,外部客户端访问系统已经有了统一入口,既然这些检验与具体业务无关,那就在请求到达的时候完成检验和过滤,而不是转发后再过滤导致更长的请求延迟,同时,通过在网关中完成校验和过滤,微服务应用端就可以去除各种复杂的国旗和拦截器,这样使得微服务应用接口的开发和测试复杂度也降低。
为了在API网关中实现对客户端请求的检验。Spring Cloud Zuul另外一个核心功能就是请求过滤。实现非常简单是许集成ZuulFilter抽象类并实现它定义的4个抽象函数就可以完成对请求拦截和过滤了。
ZuulFilter是在zuul-core-1.3.0.jar。
4个抽象函数ZuuFilter里有两个,IZuulFilter里面有两个,具体源码如下。
Spring Cloud Zuul中实现的过滤器必选包含4个基本特征:过滤请求、执行顺序,执行条件、具体操作。这四个条件就是要继承ZuuFilter重写的四个方法。
- //在ZuulFilter抽象类中定义的
- 1.abstract public String filterType();
- 2.abstract public int filterOrder();
- //在IZuulFilter接口中定义的
- 3. boolean shouldFilter();
- 4. Object run();
具体各自的功能如下:
- filterType:该函数需要返回一个字符串代表过滤器的类型,而这个类型就是在HTTP请求过程的各个阶段(即整个HTTP的声明周期)。在zuul中默认定义了4种不同声明周期的过滤器类型:如下
1.pre:可以在请求被路由之前调用
2.routing:在请求时被调用
3.post:在routing和error过滤之后调用。
4.error:处理请求时发生错误是被调用。
- filterOrder:通过int值来定义过滤器的执行顺序,数据值越小优先级越高。
- shouldFilter:返回一个boolean值来判断过滤器是否要执行。可以通过此方法来指定过滤器的有效范围。
- run:过滤的具体逻辑。在该函数中,可以实现自定义的过滤逻辑,来确定是否要拦截当前请求,不对其进行后续的路由,或是在请求路由返回结果之后,对处理结果做一些加工。
filterType 4个类型对于整个HTTP声明周期的控制图如下:
上面几个核心过滤器是在spring-cloud-netflix-core.jar文件下。
演示
pom.xml
启动类
package com.niugang; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.Bean; import com.niugang.config.AccessFilter; /** * zuul启动类 * * @author niugang * */ @SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker //可以直接用@SpringCloudApplication注解,该注解包含上面三个注解 /* *设置一个Zuul服务器端点并在其中安装一些反向代理过滤器,这样它就可以将请求转发给后端服务器 */ @EnableZuulProxy public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } //配置filter @Bean public AccessFilter accessFilter(){ return new AccessFilter(); } }
ZuulFilter
服务消费者,api网关
输入:http://localhost:8777/api-a/feign-consumer 显示
输入:http://localhost:8777/api-a/feign-consumer?accessToken=11 显示
微信公众号