电子商务平台源码请加企鹅求求:三伍三六贰四柒二伍九。本文咱们将具体介绍一下Spring Cloud Zuul的另外一项核心功能:过滤器。web
过滤器的做用api
经过上面所述的两篇咱们,咱们已经可以实现请求的路由功能,因此咱们的微服务应用提供的接口就能够经过统一的API网关入口被客户端访问到了。可是,每一个客户端用户请求微服务应用提供的接口时,它们的访问权限每每都须要有必定的限制,系统并不会将全部的微服务接口都对它们开放。然而,目前的服务路由并无限制权限这样的功能,全部请求都会被毫无保留地转发到具体的应用并返回结果,为了实现对客户端请求的安全校验和权限控制,最简单和粗暴的方法就是为每一个微服务应用都实现一套用于校验签名和鉴别权限的过滤器或拦截器。不过,这样的作法并不可取,它会增长往后的系统维护难度,由于同一个系统中的各类校验逻辑不少状况下都是大体相同或相似的,这样的实现方式会使得类似的校验逻辑代码被分散到了各个微服务中去,冗余代码的出现是咱们不但愿看到的。因此,比较好的作法是将这些校验逻辑剥离出去,构建出一个独立的鉴权服务。在完成了剥离以后,有很多开发者会直接在微服务应用中经过调用鉴权服务来实现校验,可是这样的作法仅仅只是解决了鉴权逻辑的分离,并无在本质上将这部分不属于业余的逻辑拆分出原有的微服务应用,冗余的拦截器或过滤器依然会存在。安全
对于这样的问题,更好的作法是经过前置的网关服务来完成这些非业务性质的校验。因为网关服务的加入,外部客户端访问咱们的系统已经有了统一入口,既然这些校验与具体业务无关,那何不在请求到达的时候就完成校验和过滤,而不是转发后再过滤而致使更长的请求延迟。同时,经过在网关中完成校验和过滤,微服务应用端就能够去除各类复杂的过滤器和拦截器了,这使得微服务应用的接口开发和测试复杂度也获得了相应的下降。bash
为了在API网关中实现对客户端请求的校验,咱们将须要使用到Spring Cloud Zuul的另一个核心功能:过滤器。并发
Zuul容许开发者在API网关上经过定义过滤器来实现对请求的拦截与过滤,实现的方法很是简单,咱们只须要继承ZuulFilter抽象类并实现它定义的四个抽象函数就能够完成对请求的拦截和过滤了。ide
过滤器的实现函数
好比下面的代码,咱们定义了一个简单的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
@SpringCloudApplication
public 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过滤器的基本功能就以介绍完毕。