spring cloud-zuul的Filter详解
来源:互联网 发布:vue.js和react.js 编辑:程序博客网 时间:2024/05/15 23:44
在前面我们使用zuul搭建了网关http://blog.csdn.net/liuchuanhong1/article/details/59056278
关于网关的作用,这里就不再次赘述了,我们今天的重点是zuul的Filter。通过Filter,我们可以实现安全控制,比如,只有请求参数中有用户名和密码的客户端才能访问服务端的资源。那么如何来实现Filter了?
要想实现Filter,需要以下几个步骤:
1、继承ZuulFilter类,为了验证Filter的特性,我们这里创建3个Filter
根据用户名来过滤
package com.chhliu.springcloud.zuul;import javax.servlet.http.HttpServletRequest;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;public class AccessUserNameFilter extends ZuulFilter {@Overridepublic Object run() {RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); System.out.println(String.format("%s AccessUserNameFilter request to %s", request.getMethod(), request.getRequestURL().toString())); String username = request.getParameter("username");// 获取请求的参数 if(null != username && username.equals("chhliu")) {// 如果请求的参数不为空,且值为chhliu时,则通过 ctx.setSendZuulResponse(true);// 对该请求进行路由 ctx.setResponseStatusCode(200); ctx.set("isSuccess", true);// 设值,让下一个Filter看到上一个Filter的状态 return null; }else{ ctx.setSendZuulResponse(false);// 过滤该请求,不对其进行路由 ctx.setResponseStatusCode(401);// 返回错误码 ctx.setResponseBody("{\"result\":\"username is not correct!\"}");// 返回错误内容 ctx.set("isSuccess", false); return null; }}@Overridepublic boolean shouldFilter() {return true;// 是否执行该过滤器,此处为true,说明需要过滤}@Overridepublic int filterOrder() {return 0;// 优先级为0,数字越大,优先级越低}@Overridepublic String filterType() {return "pre";// 前置过滤器}}通过继承ZuulFilter然后覆写上面的4个方法,就可以实现一个简单的过滤器,下面就相关注意点进行说明
filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
pre
:可以在请求被路由之前调用route
:在路由请求时候被调用post
:在route和error过滤器之后被调用error
:处理请求时发生错误时被调用
filterOrder
:通过int值来定义过滤器的执行顺序
shouldFilter
:返回一个boolean类型来判断该过滤器是否要执行,所以通过此函数可实现过滤器的开关。在上例中,我们直接返回true,所以该过滤器总是生效
run
:过滤器的具体逻辑。需要注意,这里我们通过ctx.setSendZuulResponse(false)
令zuul过滤该请求,不对其进行路由,然后通过ctx.setResponseStatusCode(401)
设置了其返回的错误码
过滤器间的协调
过滤器没有直接的方式来访问对方。 它们可以使用RequestContext共享状态,这是一个类似Map的结构,具有一些显式访问器方法用于被认为是Zuul的原语,内部是使用ThreadLocal实现的,有兴趣的同学可以看下源码。
再建一个过滤器,根据密码来过滤:
package com.chhliu.springcloud.zuul;import javax.servlet.http.HttpServletRequest;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;public class AccessPasswordFilter extends ZuulFilter {@Overridepublic Object run() {RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); System.out.println(String.format("%s AccessPasswordFilter request to %s", request.getMethod(), request.getRequestURL().toString())); String username = request.getParameter("password"); if(null != username && username.equals("123456")) { ctx.setSendZuulResponse(true); ctx.setResponseStatusCode(200); ctx.set("isSuccess", true); return null; }else{ ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); ctx.setResponseBody("{\"result\":\"password is not correct!\"}"); ctx.set("isSuccess", false); return null; }}@Overridepublic boolean shouldFilter() {RequestContext ctx = RequestContext.getCurrentContext();return (boolean) ctx.get("isSuccess");// 如果前一个过滤器的结果为true,则说明上一个过滤器成功了,需要进入当前的过滤,如果前一个过滤器的结果为false,则说明上一个过滤器没有成功,则无需进行下面的过滤动作了,直接跳过后面的所有过滤器并返回结果}@Overridepublic int filterOrder() {return 1; // 优先级设置为1}@Overridepublic String filterType() {return "pre";}}最后建一个post过滤器
package com.chhliu.springcloud.zuul;import javax.servlet.http.HttpServletRequest;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;public class AccessTokenFilter extends ZuulFilter {@Overridepublic Object run() {RequestContext ctx = RequestContext.getCurrentContext();HttpServletRequest request = ctx.getRequest();System.out.println(String.format("%s AccessTokenFilter request to %s", request.getMethod(),request.getRequestURL().toString()));ctx.setSendZuulResponse(true);ctx.setResponseStatusCode(200);ctx.setResponseBody("{\"name\":\"chhliu\"}");// 输出最终结果return null;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic int filterOrder() {return 0;}@Overridepublic String filterType() {return "post";// 在请求被处理之后,会进入该过滤器}}2、在主类中,先开启前面的两个过滤器
@Beanpublic AccessUserNameFilter accessUserNameFilter() {return new AccessUserNameFilter();}@Beanpublic AccessPasswordFilter accessPasswordFilter(){return new AccessPasswordFilter();}3、输入请求,验证
(1)请求为:http://localhost:8768/h2service/user/1?username=chhliu
测试结果为:
{"result":"password is not correct!"}控制台打印结果
GET AccessUserNameFilter request to http://localhost:8768/h2service/user/1GET AccessPasswordFilter request to http://localhost:8768/h2service/user/1通过了AccessUserNameFilter过滤器,在验证AccessPasswordFilter过滤器的时候失败了
后台无sql打印,说明请求没有被路由
(2)请求为:http://localhost:8768/h2service/user/1?password=123456
测试结果为:
{"result":"username is not correct!"}控制台打印结果:
GET AccessUserNameFilter request to http://localhost:8768/h2service/user/1说明到了AccessUserNameFilter过滤器,但是没有到AccessPasswordFilter过滤器,因为AccessUserNameFilter过滤器的优先级高一些,会先执行,在执行的时候,发现过滤条件不符合,于是跳过了后面所有的过滤器,并返回结果
后台无sql打印,说明请求没有被路由
(3)请求为:http://localhost:8768/h2service/user/1?password=123456&username=chhliu
测试结果为:
{ "id": 1, "username": "user1", "name": "张三", "age": 20, "balance": 100.00}控制台打印的结果:
GET AccessUserNameFilter request to http://localhost:8768/h2service/user/1GET AccessPasswordFilter request to http://localhost:8768/h2service/user/1说明是先执行了AccessUserNameFilter然后才执行AccessPasswordFilter这也和我们前面说的order的值越小,优先级越高是吻合的。
同时被请求的服务有sql输出:
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.balance as balance3_0_0_, user0_.name as name4_0_0_, user0_.username as username5_0_0_ from user user0_ where user0_.id=?说明请求被路由了。
4、开启post过滤器,再跑一次
测试结果:发现post过滤器是最后执行的,尽管它的优先级为0
关于zuul的Filter的生命周期,见下图
注:上图有个小错误,routing应该是route
5、拓展
zuul还提供了一类特殊的过滤器,分别为:StaticResponseFilter和SurgicalDebugFilter
StaticResponseFilter:StaticResponseFilter允许从Zuul本身生成响应,而不是将请求转发到源。
SurgicalDebugFilter:SurgicalDebugFilter允许将特定请求路由到分隔的调试集群或主机。
- spring cloud-zuul的Filter详解
- spring cloud-zuul的Filter详解
- spring cloud-zuul的Filter详解
- spring cloud-zuul的Filter详解
- spring cloud网关zuul之filter注册
- Spring Cloud (13) | Router and Filter: Zuul
- Spring cloud Zuul Filter 使用小经验
- Spring Cloud 的 Zuul 过滤器
- spring cloud网关zuul源码之Filter管理
- Spring Cloud(七)服务网关 Zuul Filter 使用
- Spring Cloud Zuul 的 route 运行机制分析
- 五、Spring Cloud 的 Zuul 网关组件
- Spring Cloud 的 Zuul 上传文件
- Spring Cloud 的 Zuul 高可用HA
- Spring Cloud 的 Zuul 聚合微服务
- spring cloud的网关服务Zuul
- spring cloud Zuul 理解
- spring cloud 之 zuul
- MVC模式与三层架构的区别
- 简单的爬虫
- 界面的设计及实现
- 前端跨域访问--PHP设置(含laravel设置方法)
- 苹果开发者账号申请流程
- spring cloud-zuul的Filter详解
- Duilib 中滚动条自动滚动到底的方法
- 9.17 test solution.
- 简单的安卓点击按钮跳转示例(整蛊扣费)
- http协议以及Servlet
- 分布式事务的典型处理方式:2PC、TCC、异步确保和最大努力型
- python中xgboost说明文档
- HTTP Cookie
- Vue2 向Vue.extend传参-propsData属性