/**
* 过滤器 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();
}
}
ZuulFilter做token校验以及做前置和后置过滤器,限流过滤器
最新推荐文章于 2022-03-20 17:04:24 发布