Zuul网关过滤器
Zuul它包含了两个核心功能:对请求的路由和过滤。
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础;而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。其实,路由功能在真正运行时,它的路由映射和请求转发同样也由几个不同的过滤器完成的。所以,过滤器可以说是Zuul实现API网关功能最为核心的部件,每一个进入Zuul的HTTP请求都会经过一系列的过滤器处理链得到请求响应并返回给客户端。
Zuul 中的过滤器跟我们之前使用的 javax.servlet.Filter 不一样,javax.servlet.Filter 只有一种类型,可以通过配置 urlPatterns 来拦截对应的请求。
Zuul 中的过滤器总共有 4 种类型,且每种类型都有对应的使用场景。
过滤的结构图
PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP
Header、收集统计信息和指标、将响应从微服务发送给客户端等。
ERROR:在其他阶段发生错误时执行该过滤器
PRE过滤器的案例
Pre过滤器的适用场景:身份认证,脱敏处理,编码集的统一设置……
过滤器的方法讲解
/**
* 身份认证过滤器
*/
@Component
public class IdentityAuthFilter extends ZuulFilter {
/**
* 用来指定过滤器的类型
* pre route post error
* @return
*/
@Override
public String filterType() {
return PRE_TYPE;
}
/**
* 过滤器的顺序
* @return 返回的Int越小,越先执行
* 每个过滤器,默认都有一个中间值5
*/
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER - 1;
}
/**
* 用来判断哪些路径,是需要做过滤处理的
* @return true 需要做过滤(就是需要执行run()) false 不需要做过滤(就是不需要执行run())
*/
@Override
public boolean shouldFilter() {
return false;
}
/**
* 具体的过滤器规则
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
return null;
}
}
热部署配置
-
在pom.xml中,添加热部署的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>
-
在application.yml,开启热部署
spring: application: name: micro-zuul-server devtools: restart: enabled: true additional-paths: /src/main/java exclude: WEB-INF/**
-
勾选IDEA热部署规则
身份认证过滤器
导入fastjson的依赖,导入commons微服务的依赖
<!--导入公共模块-->
<dependency>
<groupId>com.woniuxy</groupId>
<artifactId>micro-common-server</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
在commons中,创建res目录,并导入响应实体类
/**
* 响应实体对象
*/
@Data
@Builder
public class ResponseMsg implements Serializable {
/**
* 在使用@Buidler后,如果要自定义构造器,需要使用该注解才生效
*/
@Tolerate
public ResponseMsg(){
}
private Integer code;
private String msg;
/**
* 返回的消息
*/
private Object data;
}
基础认证(垃圾的方案)
垃圾方案:模拟Cookie +Session 向后端通过Header传递JSessionId数据
/**
* 身份认证过滤器
*/
@Component
public class IdentityAuthFilter extends ZuulFilter {
/**
* 用来指定过滤器的类型
* pre route post error
* @return
*/
@Override
public String filterType() {
return PRE_TYPE;
}
/**
* 过滤器的顺序
* @return 返回的Int越小,越先执行
* 每个过滤器,默认都有一个中间值5
*/
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER - 1;
}
/**
* 用来判断哪些路径,是需要做过滤处理的
* @return true 需要做过滤(就是需要执行run()) false 不需要做过滤(就是不需要执行run())
*/
@Override
public boolean shouldFilter() {
//请求上下文对象
RequestContext requestContext = RequestContext.getCurrentContext();
//获得请求对象
HttpServletRequest request = requestContext.getRequest();
//获得请求路径
String path = request.getRequestURI();// 某个微服务/请求路径
// request.getRequestURL();// http://ip:port/某个微服务/请求路径
System.out.println("path------" + path);
/*注册方法,登录方法 这些是不需要执行过滤处理的*/
if(path.equals("/micro-permission-server/admin/login")
|| path.equals("/micro-permission-server/admin/register")){
return false;
}
return true;
}
/**
* 具体的过滤器规则
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
System.out.println("执行过滤方法");
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//从Http Header中,判断是否有JsessionId的存在
String val = request.getHeader("JsessionId");
if(StringUtils.hasLength(val)){
//有长度,暂时默认成功
System.out.println("进入到微服务");
}else{//如果没有长度,或者为NULL,设置响应失败(401)
//不进入到下一步(route过滤器)
requestContext.setSendZuulResponse(false);
//设置响应数据
HttpServletResponse response = requestContext.getResponse();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
requestContext.setResponse(response);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
requestContext.setResponseBody(JSONObject.toJSONString
(ResponseMsg.builder().code(10001).msg("未进行身份认证").build()));
}
return null;
}
}
esponseStatusCode(HttpStatus.UNAUTHORIZED.value());
requestContext.setResponseBody(JSONObject.toJSONString
(ResponseMsg.builder().code(10001).msg(“未进行身份认证”).build()));
}
return null;
}
}