前言:
而今你们对“ajax中error参数”可能比较看重,大家都需要剖析一些“ajax中error参数”的相关内容。那么小编在网络上汇集了一些关于“ajax中error参数””的相关内容,希望各位老铁们能喜欢,大家一起来学习一下吧!之前公司给政府做的一个项目被公安局的网络攻击人员给破解了,现在需要给登陆接口加上错误次数限制,于是使用了spring aop + 自定义注解来做
使用注解 @Around获取 ApiLimits 注解中的参数数组 ApiLimit[] , 支持多个纬度的限制调用方法之前判断是否已经被限制Object obj = proceed(joinPoint);给对应的key (使用apiLimit 中的参数拼接而成) 在redis 中 + 1
使用方式 :
@ApiLimits({ @ApiLimit(limitTimeout = 1, limitCount = 5), @ApiLimit(limitTimeout = 3, limitCount = 20), @ApiLimit(limitTimeout = 1, limitCount = 50, unit = TimeUnit.HOURS, isRollIntoBlacklist = true) })/****该使用方式表示,注解的接口,或方法 1分钟内 只能错误5次3分钟内 只能错误20次1个小时 只能错误50次,并且到达了这个纬度,将该IP放入黑名单(黑名单逻辑单独实现,会限制该IP访问系统中的任何接口)***/
具体实现 :
package com.shumei.edu.common.annotation;import java.lang.annotation.*;/** * * 接口调用错误限制 数组 * 注意如果有多个的话,应该将条件低的放在前面,这样如果碰到条件低的都不满足的话,会直接返回,不会执行下面的 */@Target({ ElementType.PARAMETER, ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface ApiLimits{ ApiLimit[] value() ;}
package com.shumei.edu.common.annotation;import com.shumei.edu.common.enums.LimitType;import java.lang.annotation.*;import java.util.concurrent.TimeUnit;/** * 接口调用限制 */@Target({ ElementType.PARAMETER, ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface ApiLimit{ // 限制类型, IP LimitType[] limitType() default {LimitType.IP} ; // 限制时间周期单位, 默认分钟 TimeUnit unit() default TimeUnit.MINUTES; // 限制时间 int limitTimeout() default -1 ; // 限制次数 int limitCount() default -1 ; /** * 是否滚进黑名单 * @return */ boolean isRollIntoBlacklist() default false ;}
package com.shumei.edu.common.enums;/** */public enum LimitType{ /***/ IP ;}
package com.shumei.edu.framework.aspectj;import cn.hutool.core.util.StrUtil;import cn.hutool.json.JSONUtil;import com.alibaba.fastjson.JSON;import com.shumei.edu.common.annotation.ApiLimit;import com.shumei.edu.common.annotation.ApiLimits;import com.shumei.edu.common.enums.LimitType;import com.shumei.edu.common.exception.CustomException;import com.shumei.edu.common.utils.ServletUtils;import com.shumei.edu.common.utils.ip.IpUtils;import com.shumei.edu.common.web.domain.AjaxResult;import com.shumei.edu.framework.redis.redis.handle.RedisCacheEnum;import com.shumei.edu.framework.redis.redis.handle.RedisUtil;import com.shumei.edu.sys.blacklist.service.IBlackListService;import org.apache.commons.lang3.StringUtils;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.Signature;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpMethod;import org.springframework.stereotype.Component;import org.springframework.web.multipart.MultipartFile;import org.springframework.web.servlet.HandlerMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.lang.reflect.Method;import java.util.Arrays;import java.util.Map;import java.util.Objects;/** * 接口调用错误限制 数组 * 注意如果有多个的话,应该将条件低的放在前面,这样如果碰到条件低的都不满足的话,会直接返回,不会执行下面的 */@Aspect@Componentpublic class ApiLimitsAspect { private static final Logger log = LoggerFactory.getLogger(ApiLimitsAspect.class); @Autowired private RedisUtil redisUtil; @Autowired private IBlackListService blackListService; // 配置织入点 @Pointcut("@annotation(com.shumei.edu.common.annotation.ApiLimits)") public void logPointCut() { } @Around(value = "logPointCut()") public Object around(ProceedingJoinPoint pjp) throws Exception { return handleLog(pjp); } protected Object handleLog(final ProceedingJoinPoint joinPoint) throws Exception { ApiLimit[] apiLimits = getAnnotationValues(joinPoint); Object checkResult = checkLimitBefore(apiLimits); if (checkResult instanceof AjaxResult){ return checkResult ; } Object obj = proceed(joinPoint); if (!isRequestFail(obj)) { return obj ; } checkResult = checkLimitAfter(apiLimits); if (checkResult instanceof AjaxResult){ return checkResult ; } return obj ; } /** * 判断是否请求失败 * @return */ private boolean isRequestFail(Object obj) { if (obj instanceof Throwable){ return true ; } Object jsonResult = Objects.isNull(obj) ? "" : obj; boolean isRequestFail = true; int code = 0; if (jsonResult instanceof AjaxResult) { code = Integer.valueOf(((AjaxResult) jsonResult).getCode()); } else { boolean flag = JSONUtil.isJson(jsonResult.toString()); if (flag) { code = JSONUtil.parseObj(jsonResult.toString()).getInt("code"); } } isRequestFail = code != 0; return isRequestFail; } private Object proceed(ProceedingJoinPoint joinPoint){ try { return joinPoint.proceed(); } catch (CustomException e) { return AjaxResult.error(e.getMessage()); } catch (Throwable throwable) { throwable.printStackTrace(); return AjaxResult.error(throwable.getMessage()); } } public Object checkLimitAfter(ApiLimit[] apiLimits){ String fullKey = ""; for (int i = 0; i < apiLimits.length; i++) { ApiLimit apiLimit = apiLimits[i]; LimitType[] limitTypes = apiLimit.limitType(); if (Arrays.asList(limitTypes).contains(LimitType.IP)) { String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); String uri = ServletUtils.getRequest().getRequestURI(); fullKey = "{}:{}:{}:{}:{}:{}" ; fullKey = StrUtil.format(fullKey, LimitType.IP.name(), ip, apiLimit.unit().name(), apiLimit.limitTimeout(), apiLimit.limitCount(), uri); Integer count = redisUtil.getObject(RedisCacheEnum.apiLimit, fullKey, Integer.class); count = Objects.isNull(count) ? 0 : count; if (count >= apiLimit.limitCount()) { if (apiLimit.isRollIntoBlacklist()) { boolean flag = blackListService.add(ip); log.info("加入黑名单 结果 {}, IP {}", flag, ip); } return AjaxResult.error("失败次数频繁,请稍后再试!"); } else { long failCount = redisUtil.incrRange(RedisCacheEnum.apiLimit, fullKey, apiLimit.unit(), apiLimit.limitTimeout()); log.info("key: {} , 失败次数: {}, 最大失败次数:{}", fullKey, failCount + 1, apiLimit.limitCount()); } } } return null ; } public Object checkLimitBefore(ApiLimit[] apiLimits){ String fullKey = ""; for (int i = 0; i < apiLimits.length; i++) { ApiLimit apiLimit = apiLimits[i]; LimitType[] limitTypes = apiLimit.limitType(); if (Arrays.asList(limitTypes).contains(LimitType.IP)) { String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); String uri = ServletUtils.getRequest().getRequestURI(); fullKey = "{}:{}:{}:{}:{}:{}" ; fullKey = StrUtil.format(fullKey, LimitType.IP.name(), ip, apiLimit.unit().name(), apiLimit.limitTimeout(), apiLimit.limitCount(), uri); Integer count = redisUtil.getObject(RedisCacheEnum.apiLimit, fullKey, Integer.class); count = Objects.isNull(count) ? 0 : count; if (count >= apiLimit.limitCount()) { if (apiLimit.isRollIntoBlacklist()) { boolean flag = blackListService.add(ip); log.info("加入黑名单 结果 {}, IP {}", flag, ip); } return AjaxResult.error("失败次数频繁,请稍后再试!"); } } } return null ; } /** * 是否存在注解,如果存在就获取 */ private ApiLimits getAnnotation(JoinPoint joinPoint) throws Exception { Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); if (method != null) { return method.getAnnotation(ApiLimits.class); } return null; } /** * 是否存在注解,如果存在就获取 */ private ApiLimit[] getAnnotationValues(JoinPoint joinPoint) throws Exception { ApiLimits apiLimits = getAnnotation(joinPoint); if (apiLimits != null) { return apiLimits.value(); } return null; }}
版权声明:
本站文章均来自互联网搜集,如有侵犯您的权益,请联系我们删除,谢谢。
标签: #ajax中error参数