ZuulFilter

欢迎光临我的博客[http://poetize.cn],前端使用Vue2,聊天室使用Vue3,后台使用Spring Boot

在服务网关中定义过滤器,只需要继承ZuulFilter抽象类,实现其定义的四个抽象函数,就可对请求进行拦截与过滤

过滤器两个功能:

  1. 路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础
  2. 过滤器功能则负责对请求的处理过程进行预干预,是实现请求校验、服务聚合等功能的基础

请求生命周期

  1. pre :在请求路由到目标之前执行。一般用于请求认证、负载均衡和日志记录
  2. route :在路由请求时候被调用,处理目标请求
  3. post :在route和error过滤器之后被调用,一般会在此步骤添加响应头、收集统计和性能数据等
  4. error :处理请求时发生错误时被调用

第一阶段:pre类型的过滤器处理

第二个阶段:routing,路由请求转发阶段
    请求将会被routing类型过滤器处理,这里的具体处理内容就是将外部请求转发到具体服务实例上去的过程
    当服务实例将请求结果都返回之后,routing阶段完成

第三个阶段:post,此时请求将会被post类型的过滤器进行处理
    这些过滤器在处理的时候不仅可以获取到请求信息,还能获取到服务实例的返回信息,
    所以在post类型的过滤器中,我们可以对处理结果进行一些加工或转换等内容。

一个特殊的阶段:error,该阶段只有在上述三个阶段中发生异常的时候才会触发
    但是它的最后流向还是post类型的过滤器,因为它需要通过post过滤器将最终结果返回给请求客户端

网站前台的token转发(经过网关,头信息会丢失)

@Component
public class WebFilter extends ZuulFilter {
    /**
     * pre :在请求路由到目标之前执行。一般用于请求认证、负载均衡和日志记录
     * route :在路由请求时候被调用,处理目标请求
     * post :在route和error过滤器之后被调用,一般会在此步骤添加响应头、收集统计和性能数据等
     * error :处理请求时发生错误时被调用
     */
    @Override
    public String filterType() {
        return "pre";   //"pre"代表前置过滤器
    }

    @Override
    public int filterOrder() {
        return 0;   //通过int值来定义过滤器的执行顺序,优先级为0,数字越大,优先级越低
    }

    @Override
    public boolean shouldFilter() {
        return true;    //执行过滤器的条件,开启过滤器
    }
    
    @Override
    public Object run() throws ZuulException {  //过滤器的具体逻辑
        //向header中添加鉴权令牌
        RequestContext requestContext = RequestContext.getCurrentContext();
        //获取header
        HttpServletRequest request = requestContext.getRequest();
        String authorization = request.getHeader("Authorization");
        if (authorization != null) {
            requestContext.addZuulRequestHeader("Authorization", authorization);
        }
        return null;
    }
}

管理后台过滤器实现token校验

public class WebFilter extends ZuulFilter {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public String filterType() {
        return "pre";   //"pre"代表前置过滤器
    }

    @Override
    public int filterOrder() {
        return 0;   //通过int值来定义过滤器的执行顺序,优先级为0,数字越大,优先级越低
    }

    @Override
    public boolean shouldFilter() {
        return true;    //开启过滤器
    }

    @Override
    public Object run() throws ZuulException {  //过滤器的具体逻辑
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        if (request.getMethod().equals("OPTIONS")) return null;   //网关转发内部请求,直接放行
        if (request.getRequestURI().indexOf("login") > 0) return null;   //登陆放行

        String authHeader = request.getHeader("Authorization"); //获取头信息
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7); //获取Token
            Claims claims = jwtUtil.parseJWT(token);    //解析Token
            if (claims != null) {
                if ("admin".equals(claims.get("roles"))) {
                    requestContext.addZuulRequestHeader("Authorization", authHeader);
                    System.out.println("token 验证通过,添加了头信息" + authHeader);
                    return null;
                }
            }
        }

        /**
         * 通过 requestContext.setSendZuulResponse(false) 令zuul过滤该请求,不对其进行路由
         * 通过 requestContext.setResponseStatusCode(403) 设置了其返回的错误码
         */
        requestContext.setSendZuulResponse(false);  //终止运行
        requestContext.setResponseStatusCode(403);  //http状态码
        requestContext.setResponseBody("权限不足");

        requestContext.getResponse().setContentType("text/html;charset=UTF‐8");
        return null;
    }
}
posted @ 2019-08-31 22:48  LittleDonkey  阅读(302)  评论(0编辑  收藏  举报