17. Zuul 过滤器

Pre和Post过滤器

在这里插入图片描述
通过Zuul Pre 过滤器做参数校验

/**
 * 参数校验 校验过来的请求是否都带了tocken
 * Created By 白
 * 2019/1/2410:34
 */
@Component
public class TockienFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

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

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext=RequestContext.getCurrentContext();
        HttpServletRequest request=requestContext.getRequest();

        //从url参数获取 也可以从cookie,header获取
        String token=request.getParameter("token");
        if (StringUtils.isEmpty(token)){
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        return null;
    }
}

它们各自的含义与功能总结如下:

filterType:该函数需要返回一个字符串来代表过滤器的类型,而这个类型就是在HTTP请求过程中定义的各个阶段。在Zuul中默认定义了四种不同生命周期的过滤器类型,具体如下:
pre:可以在请求被路由之前调用。
routing:在路由请求时候被调用。
post:在routing和error过滤器之后被调用,也就是请求调用后。
error:处理请求时发生错误时被调用。

filterOrder:通过int值来定义过滤器的执行顺序,数值越小优先级越高。

shouldFilter:返回一个boolean类型来判断该过滤器是否要执行。我们可以通过此方法来指定过滤器的有效范围。

run:过滤器的具体逻辑。在该函数中,我们可以实现自定义的过滤逻辑,来确定是否要拦截当前的请求,不对其进行后续的路由,或是在请求路由返回结果之后,对处理结果做一些加工等。

此时通过Zuul访问其他服务的接口必须带token否则返回401
在这里插入图片描述
在这里插入图片描述
通过Zuul Post 过滤器给返回结果的Header添加信息

/**
 * 在返回的header中添加东西
 * Created By 白鹏
 * 2019/1/2411:00
 */
@Component
public class addResponseHeaderFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return POST_TYPE;
    }

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

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext=RequestContext.getCurrentContext();
        HttpServletResponse response=requestContext.getResponse();
        response.setHeader("X-Foo", UUID.randomUUID().toString());
        return null;
    }
}

在这里插入图片描述

限流

所有的请求都经过Zuul,所以可以通过限流来防止网络攻击

时机:请求被转发之前调用

令牌桶限流:首先根据一定速率给令牌桶放令牌,当满了就丢弃掉。当请求过来,那么先获取令牌,获取到令牌的就放行,获取不到的就拒绝。
在这里插入图片描述

@Component
public class RateLimitFilter extends ZuulFilter {

    //创建google令牌桶限流组件,每隔一秒放100个令牌
    private static final RateLimiter RATE_LIMITER=RateLimiter.create(100);

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {

        return SERVLET_DETECTION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        //去取令牌 如果没有取到 那么抛个异常
        if (!RATE_LIMITER.tryAcquire()){
           throw new RateLimitException();
        }
        return null;
    }
}

鉴权

首先在登陆方 放一个标识
卖家登陆 Cookie放入token 同时放入 redis

/**
     * 卖家登陆
     * @param openId
     * @param response
     * @return
     */
    @GetMapping("/seller")
    public ResultVO seller(@RequestParam("openId")String openId, HttpServletResponse response, HttpServletRequest request){
        //判断是否已经登陆
        Cookie cookie=CookieUtil.get(request,CookieConstant.TOKEN);
        if (cookie!=null &&
                StringUtils.isNotEmpty(stringRedisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_TEMPLATE.toString(),cookie.getValue())))){
            return ResultVOUtil.success();
        }

        //查询
        UserInfo info=userService.findByOpenId(openId);

        //判断信息是否为空
        if (info==null){
            return ResultVOUtil.error(ResultEnum.LOGIN_FAIL);
        }

        //判断角色
        if (!RoleEnom.seller.getCode().equals(info.getRole())){
            return ResultVOUtil.error(ResultEnum.ROLE_ERROR);
        }

        //写入redis
        String token= UUID.randomUUID().toString();
        Integer expire = CookieConstant.expire;
        stringRedisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_TEMPLATE.toString(),token),openId,expire, TimeUnit.SECONDS);

        //设置Cookie
        CookieUtil.set(response, CookieConstant.TOKEN,token,CookieConstant.expire);

        return ResultVOUtil.success();
    }

卖家对某个接口进行拦截

@Component
public class AuthSellerFilter extends ZuulFilter {


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

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

    @Override
    public boolean shouldFilter() {
        RequestContext requestContext=RequestContext.getCurrentContext();
        HttpServletRequest request=requestContext.getRequest();
        if ("/order/order/finish".equals(request.getServletPath())) {
            return true;
        }
        return  false;
    }

    @Override
    public Object run() throws ZuulException {

        /**
         * /order/finish 只能卖家访问 (cookie里有token)
         */
        RequestContext requestContext=RequestContext.getCurrentContext();
        HttpServletRequest request=requestContext.getRequest();

        Cookie cookie=CookieUtil.get(request,CookieConstant.TOKEN);
        if(cookie==null
                || StringUtils.isEmpty(cookie.getValue())
                 || StringUtils.isEmpty(stringRedisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_TEMPLATE,cookie.getValue())))){
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }

        return null;
    }
}

跨域

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter(){
        final UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config=new CorsConfiguration();

        config.setAllowCredentials(true);
        config.setAllowedOrigins(Arrays.asList("*"));
        config.setAllowedHeaders(Arrays.asList("*"));
        config.setAllowedMethods(Arrays.asList("*"));
        config.setMaxAge(300L);

        source.registerCorsConfiguration("/**",config);
        return new CorsFilter(source);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值