服务网关ZuulFilter过滤器--pre/post/error的用法(校验请求信息,获取路由后的请求/响应信息,处理服务网关异常)
微服务中Zuul服务网关一共定义了四种类型的过滤器:
- pre:在请求被路由(转发)之前调用
- route:在路由(请求)转发时被调用
- error:服务网关发生异常时被调用
- post:在路由(转发)请求后调用
我在项目中用到了,pre/error/post三种类型,先记录一下
pre过滤器主要是用来校验各种信息的
import com.alibaba.fastjson.JSONObject;
import com.dkjk.gateway.context.ResponseBean;
import com.dkjk.gateway.domain.DockCompanyService;
import com.dkjk.gateway.domain.UserService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter; /**
* @author: qjc
* @createTime: 2019/4/13 16:08
* @Description: 接口安全验证过滤器
*/
@Component
@Slf4j
public class ValidFilter extends ZuulFilter { @Override
public String filterType() {
return "pre";
} @Override
public int filterOrder() {
return 0;
} @Override
public boolean shouldFilter() {
// 进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求来探测后续需要发起的跨域POST请求是否安全可接受
// 所以这个请求就不需要拦截,下面是处理方式
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
log.info("OPTIONS请求不做拦截操作");
return false;
}
return true;
} @Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String userToken = request.getHeader("apikey");
if (StringUtils.isBlank(userToken)) {
log.warn("apikey为空");
sendError(requestContext, 99001, "请传输参数apikey");
return null;
}
return null;
} /**
* 发送错误消息
*
* @param requestContext
* @param status
* @param msg
*/
private void sendError(RequestContext requestContext, int status, String msg) {
//过滤该请求,不往下级服务转发,到此结束不进行路由
requestContext.setSendZuulResponse(false);
HttpServletResponse response = requestContext.getResponse();
response.setHeader("Content-type", "application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter pw = null;
try {
pw = response.getWriter();
pw.write(JSONObject.toJSONString(new ResponseBean(status, msg, null)));
} catch (IOException e) {
log.error(e.getMessage());
} finally {
pw.close();
}
}
}
post过滤器可以在请求转发后获取请求信息和响应入库,或者日志记录
import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map; /**
* @author: qjc
* @createTime: 2019/5/6 11:07
* @Description:
*/
@Component
@Slf4j
public class ResponseFilter extends ZuulFilter { @Override
public String filterType() {
return "post";
} @Override
public int filterOrder() {
return 2;
} @Override
public boolean shouldFilter() {
// 进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求来探测后续需要发起的跨域POST请求是否安全可接受
// 所以这个请求就不需要拦截,下面是处理方式
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
log.info("OPTIONS请求不做拦截操作");
return false;
}
// 如果前面的拦截器不进行路由,那么后面的过滤器就没必要执行
if (!requestContext.sendZuulResponse()) {
return false;
}
return true;
} @Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
InputStream stream = requestContext.getResponseDataStream();
if (stream == null) {
return null;
} HttpServletRequest request = requestContext.getRequest(); String requestParams = getRequestParams(requestContext, request);
System.err.println(requestParams); try {
String responseBoby = IOUtils.toString(stream);
RequestContext.getCurrentContext().setResponseBody(responseBoby);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//获取请求参数,适用于POST请求/GET请求,以及参数拼接在URL后面的POST请求
private String getRequestParams(RequestContext requestContext, HttpServletRequest request) {
String requestParams = null;
String requestMethod = request.getMethod();
StringBuilder params = new StringBuilder();
Enumeration<String> names = request.getParameterNames();
if (requestMethod.equals("GET")) {
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
params.append(name);
params.append("=");
params.append(request.getParameter(name));
params.append("&");
}
requestParams = params.delete(params.length() - 1, params.length()).toString();
} else {
Map<String, String> res = new HashMap<>();
Enumeration<?> temp = request.getParameterNames();
if (null != temp) {
while (temp.hasMoreElements()) {
String en = (String) temp.nextElement();
String value = request.getParameter(en);
res.put(en, value);
}
requestParams = JSON.toJSONString(res);
}
if (StringUtils.isBlank(requestParams) || "{}".equals(requestParams)) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder("");
try {
br = request.getReader();
String str;
while ((str = br.readLine()) != null) {
sb.append(str);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
requestParams = sb.toString();
}
}
return requestParams;
}
}
error过滤器是在服务网关出现异常的时候起作用的
import com.alibaba.fastjson.JSONObject;
import com.dkjk.gateway.context.ResponseBean;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils; import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter; /**
* @author: qjc
* @createTime: 2019/5/30 19:11
* @Description: 处理请求发生错误时过滤器
*/
@Component
@Slf4j
public class ErrorFilter extends ZuulFilter {
@Override
public String filterType() {
return "error";
} @Override
public int filterOrder() {
//需要在默认的 SendErrorFilter 之前
return -1;
} @Override
public boolean shouldFilter() {
// 只有在抛出异常时才会进行拦截
return RequestContext.getCurrentContext().containsKey("throwable");
} @Override
public Object run() {
try {
RequestContext requestContext = RequestContext.getCurrentContext();
Object e = requestContext.get("throwable"); if (e != null && e instanceof ZuulException) {
ZuulException zuulException = (ZuulException) e;
// 删除该异常信息,不然在下一个过滤器中还会被执行处理
requestContext.remove("throwable");
// 响应给客户端信息
HttpServletResponse response = requestContext.getResponse();
response.setHeader("Content-type", "application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter pw = null;
pw = response.getWriter();
pw.write(JSONObject.toJSONString(new ResponseBean(99999, "系统出现异常", null)));
pw.close();
}
} catch (Exception ex) {
log.error("Exception filtering in custom error filter", ex);
ReflectionUtils.rethrowRuntimeException(ex);
}
return null;
}
}
服务网关ZuulFilter过滤器--pre/post/error的用法(校验请求信息,获取路由后的请求/响应信息,处理服务网关异常)的更多相关文章
- 服务网关ZuulFilter过滤器--如何解决跨域请求中的OPTIONS请求
进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求 来探测后续需要发起的跨域POST请求是否安全可接受 所以这个请求就不需要拦截,下面是处理方式 @Ove ...
- 微服务网关Zuul过滤器Filter
Zuul本质 Zuul是一个网关,关于网关的介绍参考:亿级流量架构之网关设计思路.常见网关对比, 可知Zuul是一个业务网关, 而深入了解Zuul, 基本就是一系列过滤器的集合: Zuul的过滤器 下 ...
- Spring Cloud架构教程 (五)服务网关(过滤器)
过滤器的作用 通过上面所述的两篇我们,我们已经能够实现请求的路由功能,所以我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了.但是,每个客户端用户请求微服务应用提供的接口时,它们 ...
- Spring Cloud(七):服务网关zuul过滤器
上文介绍了Zuul的基本使用与路由功能,本文接着介绍Zuul的核心概念 -- Zuul过滤器(filter). Zuul的功能基本通过Zuul过滤器来实现(类比于Struts的拦截器,只是Struts ...
- SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理
前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...
- TZ_14_Zuul网关_过滤器
1.Zuul作为网关的其中一个重要功能,就是实现请求的鉴权.而这个动作我们往往是通过Zuul提供的过滤器来实现的. 2.自定义过滤器实现用户登陆时需要携带一个Key才可以登陆,否则返回403 1> ...
- 使用网关zuul过滤器登录鉴权
使用网关zuul过滤器登录鉴权 1.新建一个filter包 filte有很多种 pre.post. 2.新建一个类LoginFilter,实现ZuulFilter,重写 ...
- AngularJS路由系列(4)-- UI-Router的$state服务、路由事件、获取路由参数
本系列探寻AngularJS的路由机制,在WebStorm下开发.主要包括: ● UI-Router的$state服务● UI-Router的路由事件● UI-Router获取路由参数 Angular ...
- c++ 网络编程(八) LINUX-epoll/windows-IOCP下 socket opoll函数用法 优于select方法的epoll 以及windows下IOCP 解决多进程服务端创建进程资源浪费问题
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9622548.html 锲子:关于并发服务器中的I/O复用实现方式,前面在网络编程系列四还是五来 ...
随机推荐
- hdu5387 钟表指针之间夹角(分数计算,模拟)
题意: 给你一个24格式的数字时间,(字符串),问你这个时刻时针与分针 时针与秒针 分针与秒针 之间的夹角, 我们发现 秒针每秒转6度,分针每秒转1/10度,每分转6度,时针每小时转30度,每分转1/ ...
- WebGL学习笔记(七):输入和动画
目前为止,我们绘制出来的3D物体都是静止的,接下来我们需要让桌面上的小盒子可以根据我们按键(上下键)前进后退: 输入方面,监听按键和鼠标消息直接在document上添加对应的监听就行了: 动画这块,我 ...
- 泡泡一分钟:BLVD: Building A Large-scale 5D Semantics Benchmark for Autonomous Driving
BLVD: Building A Large-scale 5D Semantics Benchmark for Autonomous Driving BLVD:构建自主驾驶的大规模5D语义基准 Jia ...
- Spring cloud微服务安全实战-7-2docker快速入门
因为后面运行的这些可视化的工具都是用docker去run 的.为了避免对docker完全没有概念的同学听不懂,帮助大家从概念上去理解docker是个什么东西. 最核心的东西就是镜像,把它理解为Spri ...
- 基于EasyDarwin开源流媒体服务器框架实现EasyNVR H5无插件直播流媒体服务器方案
背景分析 在之前的一篇博客<web无插件播放RTSP摄像机方案,拒绝插件,拥抱H5!>中,描述了实现一套H5无插件直播方案的各个组件的参考建议,又在博客<EasyNVR H5流媒体服 ...
- centos7.3部署memcached服务
我们需要下载libevent和memcached这两个压缩包进行安装,可使用以下百度网盘链接进行下载 链接:https://pan.baidu.com/s/1vehZ5odzXFKwNjWT9_W0T ...
- 【vim小记】vim的高效移动
我还是推荐所有刚入门vim的朋友先去用vimtutor练习,然后去看vim的帮助文档,写的十分仔细,而且可以马上实战,见效很快,以下的很多示意图都是vim帮助文档里的例子,我觉得很好,就拿出来了. v ...
- call、apply、bind的区别,模拟call、apply和bind的实现
bind:bind绑定完this的指向后会返回一个新的函数体,不会被立即调用 call&apply:绑定完this的指向后会立即调用 call与apply的区别: call:第 ...
- 2.Jvm 虚拟机栈和栈帧
Jvm 虚拟机栈和栈帧 1.栈帧(frames) 官网描述 A frame is used to store data and partial results, as well as to perfo ...
- flask框架(三)——路由系统route转换成add_url_rule及源码分析
这节我们不用@app.route来写路由,而是通过add_url_rule 传统写法 (<int:nid>传递int类型参数,endpoint是取别名) @app.route('/det ...