网关服务(zuul)设置路由过滤(ZuulFilter )

周末记一次笔记

ZuulFilter 的生命周期

在这里插入图片描述

过滤器类型 filterType

Zuul 中的过滤器跟我们之前使用的 javax.servlet.Filter 不一样,javax.servlet.Filter 只有一种类型,可以通过配置 urlPatterns 来拦截对应的请求。

而 Zuul 中的过滤器总共有 4 种类型,且每种类型都有对应的使用场景。
1)pre
可以在请求被路由之前调用。适用于身份认证的场景,认证通过后再继续执行下面的流程。
2)route
在路由请求时被调用。适用于灰度发布场景,在将要路由的时候可以做一些自定义的逻辑。
3)post
在 route 和 error 过滤器之后被调用。这种过滤器将请求路由到达具体的服务之后执行。适用于需要添加响应头,记录响应日志等应用场景。
4)error
处理请求时发生错误时被调用。在执行过程中发送错误时会进入 error 过滤器,可以用来统一记录错误信息。

package com.cloudyoung.zuul.filter;

import com.cloudyoung.zuul.service.RedisService;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;

@Configuration
public class PreFilter  extends  ZuulFilter {
    
    


    private final String Shiro_Session="shiro:session:";

    @Resource
    private RedisService redisService;

    private static Logger log = LoggerFactory.getLogger(PreFilter.class);
    /**
     * 请求前处理
     * @return
     */
    @Override
    public String filterType() {
    
    
        return "pre";
    }

    @Override
    public int filterOrder() {
    
    
        return  PRE_DECORATION_FILTER_ORDER - 1;
    }


    /**
     * 是否需要过滤  true 默认false
     * @return
     */
    @Override
    public boolean shouldFilter() {
    
    
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String requestUrl = request.getRequestURL().toString();
        // 请求URL内不包含login或join则需要经过该过滤器,即执行run()
        return !requestUrl.contains("login") && !requestUrl.contains("logout");
    }

    @Override
    public Object run() throws ZuulException {
    
    
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s 方式请求 %s", request.getMethod(), request.getRequestURL().toString()));
        //获取传来的参数accessToken
       // Object accessToken = request.getParameter("Authorization");
        Object accessToken = request.getHeader("Authorization");
        if(accessToken == null) {
    
    
            log.warn("Authorization token is empty");
            //过滤该请求,不往下级服务去转发请求,到此结束
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.setResponseBody("{\"result\":\"Authorization is empty!\"}");
            return null;
        }else if(accessToken!=null && !accessToken.equals("")){
    
    
            String key = String.valueOf(accessToken);
            String result = redisService.get(Shiro_Session+key);
            boolean notBlank = StringUtils.isNotBlank(result);
            if(notBlank){
    
    
                ctx.setSendZuulResponse(true);
                ctx.setResponseStatusCode(200);
                //如果有token,则进行路由转发
                log.info("Authorization token ok");
            }else{
    
    
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);
                ctx.setResponseBody("{\"result\":\"Authorization is unefftive!\"}");
            }
        }
        return null;

    }
}

使用RequestContext 传递参数

		RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();


		/过滤该请求,不往下级服务去转发请求,到此结束		
		 ctx.setSendZuulResponse(false);

该过滤器只对进入路由后的请求路径进行过滤。(、api/serach/ 或 api/portrait/ 后的请求才进行过滤 )
yml配置

#添加路由前缀 api
zuul:
  prefix: /api
  routes:
    ai-serach:
      path: /serach/**
      serviceId: ai-serach
    ai-portrait:
          path: /portrait/**
          serviceId: ai-portrait
  add-host-header: true #添加host头信息
  sensitive-headers:    #敏感头信息
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 12000   #熔断 超时时长 5000ms

#ribbon的默认超时时长:(read + connect) * 2, 必须小于hystrix的时长
ribbon:
  ConnectionTimeOut: 5000   #ribbon 链接超时时长
  ReadTimeout: 5000   #ribbon 读取超时时长
  MaxAutoRetries: 0   #ribbon 当前服务重试次数
  MaxAutoRetriesNextServer: 0   #ribbon 切换服务重试次数

猜你喜欢

转载自blog.csdn.net/qq_38893133/article/details/104727839