ZuulFilter做token校验以及做前置和后置过滤器,限流过滤器


/**
 * 过滤器 1
 * 限流过滤器
 * 这里只对登录做限流
 */
@Component
public class AccessLimitFilter extends ZuulFilter {

    @Autowired
    private AccessLimitService accessLimitService;


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

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

    @Override
    public boolean shouldFilter() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //登录路由限流
        if ("/api-a/user/login".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        }
        return false;
    }

    @SneakyThrows
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletResponse response =requestContext.getResponse();
        //这里去令牌桶取令牌,没取到则返回false,稍后重试
        try {
            if (!accessLimitService.tryAcquire()) {
                requestContext.setSendZuulResponse(false);
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json; charset=utf-8");
                response.getWriter().write(JsonUtils.obj2String(AccessLimitWarn.AccessLimitErr()));//人员过多,令牌未取到
            }else{
                requestContext.setSendZuulResponse(true);
                return true;
            }
        }catch (Exception e){
            requestContext.setSendZuulResponse(false);

        }finally {
            return false;
        }
    }
}

/**
 * 令牌桶
 */
@Service
public class AccessLimitService {

    //每秒只发出5个令牌(实际会 +1)
    RateLimiter rateLimiter = RateLimiter.create(5.0);

    /**
     * 尝试获取令牌
     * @return
     */
    public boolean tryAcquire(){
        return rateLimiter.tryAcquire();
    }
}


/**
 * 过滤器 2
 * 登录过滤器 *记得类上加Component注解
 * token 身份校验过滤器
 *
 */
@Component
public class LoginFilter extends ZuulFilter {
    @Autowired
    private TokenHelper tokenHelper;

    /**
     * 过滤器类型,前置过滤器
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * 过滤器顺序,越小越先执行
     */
    @Override
    public int filterOrder() {
        return 2;
    }

    /**
     * 过滤器是否生效
     * 返回true代表需要权限校验,false代表不需要用户校验即可访问
     */
    @Override
    public boolean shouldFilter() {
        //共享RequestContext,上下文对象
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        System.out.println(request.getRequestURI());
        //登录路由不需要权限校验
        if ("/api-a/user/login".equalsIgnoreCase(request.getRequestURI())) {
            return false;
        }
        //注册路由不需要权限校验
        if ("/api-a/user/save".equalsIgnoreCase(request.getRequestURI())) {
            return false;
        }
        return true;
    }

    /**
     * 业务逻辑
     * 只有上面返回true的时候,才会进入到该方法
     * 校验token合法性
     */
    @SneakyThrows
    @Override
    public Object run() throws ZuulException {
        //JWT
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        HttpServletResponse response =requestContext.getResponse();

        //注册路由直接通过
//        if ("/api-a/user/save".equalsIgnoreCase(request.getRequestURI())) {
//            requestContext.setSendZuulResponse(true);
//            return true;
//        }
        //token对象,有可能在请求头传递过来,也有可能是通过参数传过来,实际开发一般都是请求头方式
        String token = request.getHeader("token");

        if (StringUtils.isBlank((token))) {
            token = request.getParameter("token");
        }
        System.out.println("页面传来的token值为:" + token);

        //1 登录校验逻辑  如果token为null,则直接返回客户端,而不进行下一步接口调用
        if (StringUtils.isBlank(token)) {
            // 过滤该请求,不对其进行路由
            requestContext.setSendZuulResponse(false);
            //返回错误代码
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            response.getWriter().write(JsonUtils.obj2String(TokenStates.tokenNone()));//token不对
            return  false;
        }

        //Aes 验证解密串是否正确
        String authStrEncrypt = request.getHeader(NormalConstant.AUTHORIZATION);//header 传来的key名称 加密状态
        String  authStrDecrypt = AesEncryptUtils.decrypt(authStrEncrypt); //解密
        // 2 传来的Aes 解密串不对
        if(authStrDecrypt.equals("")){
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            requestContext.setSendZuulResponse(false);

            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            response.getWriter().write(JsonUtils.obj2String(TokenStates.tokenError()));//token不对
            return  false;
        }

        //token验证
        TokenModel model = tokenHelper.get(authStrDecrypt);
        // 3 验证通过
        if(tokenHelper.check(model)) {//在reids 中检查 key是否存在,以及是否过期
            request.setAttribute(NormalConstant.CURRENT_USER_ID, model.getUserId());//在当前request 设置 userId ,目的方便根据 userid 退出
            requestContext.setSendZuulResponse(true);
        }else{
            //验证失败,token过期
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            requestContext.setSendZuulResponse(false);
            response.getWriter().write(JsonUtils.obj2String(TokenStates.tokenExpire()));//token过期
        }
        return  null;

    }
}





/**过滤器3 后置过滤器记录操作日志
 * 接口调用日志记录过滤器
 */
@Component
public class Log  extends ZuulFilter {
    @Autowired
    private TokenHelper tokenHelper;

    private static final Logger logger = LoggerFactory.getLogger(Log.class);


    @Override
    public String filterType() {
        return POST_TYPE;//要打印返回信息,必须得用"post"
    }

    @Override
    public int filterOrder() {
        return 3;
    }

    @Override
    public boolean shouldFilter() {

        return true;
    }

    @Override
    public Object run() {
        try {
            logger.info("进入日志记录过滤器");
            Object zuulResponse = RequestContext.getCurrentContext().get("zuulResponse");
            if (zuulResponse != null) {
                RibbonHttpResponse resp = (RibbonHttpResponse) zuulResponse;
                //获取返回值信息
                String body = IOUtils.toString(resp.getBody());
                //返回结果全在这
                JSONObject json = JSONObject.parseObject(body);
                String msg =json.getString("json");
                resp.close();
                RequestContext.getCurrentContext().setResponseBody(body);
            }
        } catch (Exception e) {
            logger.error("响应异常 :{} ",  e.getMessage(),e);
        }

        return null;
    }


    String printArray(String[] arr) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            sb.append(arr[i]);
            if (i < arr.length - 1) {
                sb.append(",");
            }
        }
        return sb.toString();
    }

}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值