All Downloads are FREE. Search and download functionalities are using the official Maven repository.

wang.ramboll.extend.request.limit.interceptor.RequestFrequencyLimitInterceptor Maven / Gradle / Ivy

There is a newer version: 1.0.4-RC.1
Show newest version
package wang.ramboll.extend.request.limit.interceptor;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import wang.ramboll.extend.basic.util.HttpServletUtils;
import wang.ramboll.extend.basic.util.JsonUtils;
import wang.ramboll.extend.basic.util.MD5Utils;
import wang.ramboll.extend.request.limit.annotation.RequestFrequencyLimit;
import wang.ramboll.extend.request.limit.enums.RequestFrequencyLimitMode;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.nio.charset.Charset;

/**
 * 访问请求频率限制拦截器
 * @author WangRuibo
 */
public class RequestFrequencyLimitInterceptor implements HandlerInterceptor {

    private RequestFrequencyLimitWork requestFrequencyLimitWork;//访问频率限制实现
    private Object limitReturnObj ;//拦截时,返回的数据模型

    private static final String LIMIT_MARK = "RAMBOLL.LIMIT_MARK";//拦截标记,用于在RequestAttributes中传递,方便取消拦截处理
    private static final String LIMIT_MARK_MAX_TIMES = "RAMBOLL.LIMIT_MARK_MAX_TIMES";//拦截标记中最大请求次数,用于在RequestAttributes中传递,方便取消拦截处理

    /**
     * 访问请求频率限制拦截器 构造器
     * @param requestFrequencyLimitWork 访问频率限制实现
     * @param limitReturnObj 拦截时,返回的数据模型
     */
    public RequestFrequencyLimitInterceptor(RequestFrequencyLimitWork requestFrequencyLimitWork, Object limitReturnObj) {
        this.requestFrequencyLimitWork = requestFrequencyLimitWork;
        this.limitReturnObj = limitReturnObj;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Method method = ((HandlerMethod)handler).getMethod();
        //找到防刷拦截标记注解
        RequestFrequencyLimit rfl = null;
        if(method.isAnnotationPresent(RequestFrequencyLimit.class)){
            rfl = method.getAnnotation(RequestFrequencyLimit.class);
        } else {
            Class cls = method.getDeclaringClass();
            if(cls.isAnnotationPresent(RequestFrequencyLimit.class)){
                rfl = (RequestFrequencyLimit)cls.getAnnotation(RequestFrequencyLimit.class);
            }
        }
        if(rfl!=null){//如果有该注解
            RequestFrequencyLimitMode[] mods = rfl.limitMode();//获得配置的拦截模式
            StringBuilder source = new StringBuilder();//用于生成唯一请求标识的字符串
            if(RequestFrequencyLimitMode.contains(RequestFrequencyLimitMode.URI,mods)){//URI模式,请求URI参与生成请求标识
                source.append(request.getRequestURI()).append("|");
            }
            boolean isRequestBodyMode = RequestFrequencyLimitMode.contains(RequestFrequencyLimitMode.REQUEST_BODY,mods);//REQUEST_BODY模式
            boolean isRequestParamMode = RequestFrequencyLimitMode.contains(RequestFrequencyLimitMode.REQUEST_PARAM,mods);//REQUEST_PARAM模式
            boolean isRequestHeaderMode = RequestFrequencyLimitMode.contains(RequestFrequencyLimitMode.REQUEST_HEADER,mods);//REQUEST_HEADER模式
            boolean isRequestAttributeMode = RequestFrequencyLimitMode.contains(RequestFrequencyLimitMode.REQUEST_ATTRIBUTE,mods);//REQUEST_ATTRIBUTE模式
            boolean methodParamMode = isRequestBodyMode||isRequestParamMode||isRequestHeaderMode||isRequestAttributeMode;//如果是注解参数模式
            if(methodParamMode){
                Parameter[] parameters = method.getParameters();
                for(Parameter parameter : parameters){
                    if(isRequestBodyMode){//带有@RequestBody注解的参数,转换为Json参与生成请求标识
                        RequestBody requestParam = parameter.getAnnotation(RequestBody.class);
                        if(requestParam!=null){
                            String body = StreamUtils.copyToString(request.getInputStream(), Charset.forName("UTF-8"));
                            String data = JsonUtils.parseObjectToJson(JsonUtils.parseJsonToObject(body,parameter.getType(),true),true);
                            source.append(data).append("|");
                        }
                    }
                    if(isRequestParamMode){//带有@RequestParam注解的参数,参与生成请求标识
                        RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
                        if(requestParam!=null){
                            String paramName = requestParam.name();
                            if(StringUtils.isBlank(paramName)){
                                paramName = parameter.getName();
                            }
                            source.append("P.").append(paramName).append("=").append(JsonUtils.parseObjectToJson(request.getParameter(paramName),true)).append("|");
                        }
                    }
                    if(isRequestHeaderMode){//带有@RequestHeader注解的参数,参与生成请求标识
                        RequestHeader requestHeader = parameter.getAnnotation(RequestHeader.class);
                        if(requestHeader!=null){
                            String headerName = requestHeader.name();
                            if(StringUtils.isBlank(headerName)){
                                headerName = parameter.getName();
                            }
                            source.append("H.").append(headerName).append(":").append(JsonUtils.parseObjectToJson(request.getHeader(headerName),true)).append("|");
                        }
                    }
                    if(isRequestAttributeMode){//带有@RequestAttribute注解的参数,参与生成请求标识
                        RequestAttribute requestAttribute = parameter.getAnnotation(RequestAttribute.class);
                        if(requestAttribute!=null){
                            String attributeName = requestAttribute.name();
                            if(StringUtils.isBlank(attributeName)){
                                attributeName = parameter.getName();
                            }
                            source.append("A.").append(attributeName).append("=").append(JsonUtils.parseObjectToJson(request.getAttribute(attributeName),true)).append("|");
                        }
                    }
                }
            }
            String md5 = MD5Utils.MD5Encode(source.toString());//用MD5生成唯一请求标识
            boolean isOk = requestFrequencyLimitWork.work(md5,rfl.delay(),rfl.maxTimes());//调用处理方法确定是否需要拦截
            request.setAttribute(LIMIT_MARK,md5);//向后方传递标记
            request.setAttribute(LIMIT_MARK_MAX_TIMES,rfl.maxTimes());//向后方传递标记
            if(!isOk){//若拦截,返回默认拦截返回对象,Json格式
                HttpServletUtils.doReturnResponseJsonObject(limitReturnObj,response);
            }
            return isOk;
        } else {
            return true ;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        String limitMark = (String) request.getAttribute(LIMIT_MARK);
        if(StringUtils.isNotBlank(limitMark)){
            requestFrequencyLimitWork.cancelLimit(limitMark,(Long) request.getAttribute(LIMIT_MARK_MAX_TIMES));
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy