说明:本项目是基于springBoot,注意是基于注解的形式,利用redis的incr命令实现,仅供参考用,springBoot项目,以及redis需要自己搭建,这里不做详细描述,主要是提供思路,如果有需要交流,请大家在下面留言,话不多说,直接上代码。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 防刷注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AccessLimit {
int seconds();
int maxCount();
boolean needLogin() default true;
}
import com.alibaba.fastjson.JSON;
import com.vipkid.parent.common.Constants;
import com.vipkid.parent.common.RedisCluster;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
/**
* @program:
* @description:拦截器实现
* @author:tsh
* @create:2019-04-14 13:53
*/
@Component
public class AntiBrushInterceptor extends HandlerInterceptorAdapter {
private Logger logger = (Logger) LoggerFactory.getLogger(AntiBrushInterceptor.class);
@Autowired
private RedisCluster redisCluster;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception{
//判断请求是否方法的请求
if(handler instanceof HandlerMethod){
HandlerMethod handlerMethod = (HandlerMethod) handler;
//获取方法中的注解,看看是否有注解
AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
if(accessLimit == null){
return true;
}
int second = accessLimit.seconds();
int maxCount = accessLimit.maxCount();
boolean login = accessLimit.needLogin();
String key = request.getRequestURI();
//如果需要登录
if(login){
String token = request.getHeader(Constants.Auth.HTTP_HEADER_TOKEN);
//获取登录的session进行判断
// key += ""+"1"; //这里假设用户是1,项目中是动态获取的userId
if(token != null){
key = token + "|" +key;
}
}
//从redis中获取用户的登录次数
String value = redisCluster.get(key);
if(value != null){
Integer count = Integer.valueOf(value);
if(count < maxCount){
redisCluster.incr(key,second);
}else {
//超出访问次数
String mess = "当前总数:" + count + ";最大总数:" + maxCount;
logger.info("超出限制范围了:{}",mess);
render(response); //这里的CodeMsg是一个返回参数
return false;
}
}else {
redisCluster.set(key,"1");
}
}
return true;
}
private void render(HttpServletResponse httpServletResponse)throws Exception{
httpServletResponse.setContentType("application/json;charset=UTF-8");
OutputStream outputStream = httpServletResponse.getOutputStream();
String str = JSON.toJSONString(CodeMsg.ACCESS_LIMIT_REACHED);
outputStream.write(str.getBytes("UTF-8"));
outputStream.flush();
outputStream.close();
}
}
/**
* @program:
* @description:错误码描述
* @author:tsh
* @create:2019-04-15 10:32
*/
public class CodeMsg {
public static String ACCESS_LIMIT_REACHED = "ACCESS_LIMIT_REACHED";
}
/**
* @program:
* @description:
* @author:tsh
* @create:2019-04-14 14:15
*/
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
private AntiBrushInterceptor antiBrushInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(antiBrushInterceptor);
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 防刷注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AccessLimit {
int seconds();
int maxCount();
boolean needLogin() default true;
}
import com.vipkid.parent.dto.RetDTO;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @program:
* @description:测试类
* @author:tsh
* @create:2019-04-15 10:50
*/
@RestController
@RequestMapping(value = "/api/autiBrush")
public class AntiBrushController {
@AccessLimit(seconds = 5,maxCount = 5,needLogin = true)
@RequestMapping(value = "/test")
@ResponseBody
public RetDTO autiBrushTest(){
RetDTO result = new RetDTO(200, "基于token的防刷接口测试");
return result;
}
}