注解+aop/拦截器实现防重复点击、机刷

来源:互联网 发布:淘宝卖鞋子的好店 编辑:程序博客网 时间:2024/06/09 18:54

拦截器实现

package com.qccr.cashcow.web.interceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import com.qccr.cashcow.biz.util.IpUtil;import com.qccr.cashcow.common.core.RedisCaches;import com.qccr.cashcow.common.core.StateCodes;import com.qccr.cashcow.common.exception.SystemServerException;import com.qccr.cashcow.common.util.Logs;import com.qccr.cashcow.web.core.HttpRequestContext;import com.qccr.cashcow.web.core.annotation.HttpLimit;/** * 访问限制 *  * @author pys * * @date 2016年3月23日 下午7:57:44 */public class HttpLimitInterceptor extends HandlerInterceptorAdapter  {    private static final Logger logger = LoggerFactory.getLogger(HttpLimitInterceptor.class);    @Override    public boolean preHandle(HttpServletRequest request,            HttpServletResponse response, Object handler) throws Exception {        if (HandlerMethod.class.isInstance(handler)) {            final HandlerMethod hm = ((HandlerMethod) handler);            HttpLimit limit = hm.getMethodAnnotation(HttpLimit.class);            if (limit != null) {                String ip = getIpAddress(request);                String url = request.getRequestURL().toString();                String key = "http_limit_".concat(url);                int userId = HttpRequestContext.getClient().getUserId();                if (userId > 0) {                    key = key + userId;                } else {                    key = key + ip;                }        long count = redisTemplate.opsForValue().increment(key, 1);        System.out.println(count);        if (count == 1) {            redisTemplate.expire(key, limit.time(), limit.unit());                if (count == 1) {                    RedisCaches.expire(key, limit.time());                }                if (count > limit.times()) {                    Logs.info("用户[" + (userId > 0 ? userId : ip) + "]访问地址[" + url + "]超过了限定的次数[" + limit.times() + "]",                            logger);                    throw new Exception("短时间内访问次数超出限制");                }            }        }        return true;    }private String getIpAddress(HttpServletRequest request) {        String ip = request.getHeader("x-forwarded-for");        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("Proxy-Client-IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("WL-Proxy-Client-IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("HTTP_CLIENT_IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("HTTP_X_FORWARDED_FOR");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getRemoteAddr();        }        return ip;    }}

aop实现

package com.qccr.cashcow.web.interceptor;import java.util.concurrent.TimeUnit;import javax.servlet.http.HttpServletRequest;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import com.qccr.cashcow.common.core.StateCodes;import com.qccr.cashcow.common.exception.SystemServerException;import com.qccr.cashcow.common.util.Logs;import com.qccr.cashcow.web.core.annotation.HttpLimit;@Aspect@Componentpublic class HttpLimitContract {    private static final Logger logger = LoggerFactory.getLogger(HttpLimitContract.class);    @Autowired    private RedisTemplate<String, String> redisTemplate;    @Before("within(@org.springframework.stereotype.Controller *) && @annotation(limit)")    public void httpLimit(final JoinPoint joinPoint, HttpLimit limit) throws Exception {        System.out.print("in:");        Object[] args = joinPoint.getArgs();        HttpServletRequest request = null;        for (int i = 0; i < args.length; i++) {            if (args[i] instanceof HttpServletRequest) {                request = (HttpServletRequest) args[i];                break;            }        }        if(request == null){            throw new SystemServerException(StateCodes.OPERATE_ERROR);        }        String ip = getIpAddress(request);        String url = request.getRequestURL().toString();        String key = "http_limit_".concat(url).concat(ip);        long count = redisTemplate.opsForValue().increment(key, 1);        System.out.println(count);        if (count == 1) {            redisTemplate.expire(key, limit.time(), limit.unit());        }        if (count > limit.times()) {            Logs.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.times() + "]", logger);            throw new Exception("短时间内访问次数超出限制");        }    }    private String getIpAddress(HttpServletRequest request) {        String ip = request.getHeader("x-forwarded-for");        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("Proxy-Client-IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("WL-Proxy-Client-IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("HTTP_CLIENT_IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("HTTP_X_FORWARDED_FOR");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getRemoteAddr();        }        return ip;    }}

HttpLimit 默认1分钟2次

package com.datatrees.loan.thirdparty.validator;import java.lang.annotation.*;import java.util.concurrent.TimeUnit;/** * 访问限制 *  * @author pys * * @date 2016年3月23日 下午7:47:44 */@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface HttpLimit {     long time() default 60 * 1000L;     TimeUnit unit() default TimeUnit.MILLISECONDS;     int times() default 2;}
阅读全文
0 0
原创粉丝点击