一,背景及设计
1.需要在网关实现黑名单功能,实现拦截指定接口。黑名单用户,会加入指定黑名单列表,关联对应功能,如用户登录,用户下单,用户接单。
2.表设计
平台表:不同系统
黑名单规则:用户定义对应功能,比如登录,维护对应的url
黑名单表
3.实现思路
网关部分
1.增加黑名单开关
2.取黑名单信息(跨服务调用),并本地缓存(咖啡因),过期时间3min(测试)
3.判断当前url是否在规则中
4.判断请求是否为登录请求,是,从入参中获取手机号;否,解析token获取用户信息
5.判断用户信息是否在黑名单中
6.网关抛出自定义响应信息
黑名单应用部分
1.维护平台/规则/黑名单基础数据
2.job检查并更新黑名单过期数据
3.提供网关黑名单相关查询接口,url用户信息/规则列表,且url用户信息做redis二级缓存,及各场景刷新缓存处理
二,遇到问题
(备注:之前有实现过xxs拦截过滤器,有读取过一次流)
获取body信息时,出现如下两个问题,且问题2本地调试没问题,发布到测试环境才有问题
1.getInputStream() has already been called for this request
2.java.io.IOException: Stream close
3.从body中读取数据为空
原因是request多次读取问题,解决方案网上比较多,比较类似。
流程如下:
客户端请求 -> 网关服务 -> 经过Filter -> 经过ZuulFilter -> 应用服务接口
大概是
1.自定义Fileter过滤器
@请求首先进入该实现类;调用第二步中实现类构造方法,实现从request读取流数据(仅有的一次读取流),并写入本地变量(类似缓存,实现多次读取流数据共享);
request传递,传递第二步中自定义request入参,后续request入参变更,重写实现的类,不是最初的httpServletRequest类
2.重写HttpServletRequestWrapper
@实现1.读取request流,写入本地常量,重写 getInputStream及getReader()方法,需要多次读取body信息,调用此方法
3.实现黑名单过滤器,继承ZuulFilter
@首先获取的request是重写HttpServletRequestWrapper新类,调用第四步,获取body信息
4.实现工具类,读取body信息