SpringCloud之接口防刷技术ratelimit框架实现
此防刷技术要在zuul网关层实现,不然不起作用.
导入依赖
<!--利用接口限流方式防刷:利用redis和ratelimit依赖已经帮我们完成了接口限流功能,只需要导入依赖-->
<dependency>
<groupId>com.marcosbarbero.cloud</groupId>
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
远程仓库配置
zuul:
#禁用springboot本身的错误页面,改成使用我们自己的
SendErrorFilter:
error:
disable: true
#接口限流配置
ratelimit:
key-prefix: ratelimit-prefix
enabled: true
repository: REDIS
behind-proxy: true
add-response-headers: true
default-policy-list: #optional - 60秒钟限制访问10次will apply unless specific policy exists
- limit: 10 #optional - request number limit per refresh interval window
refresh-interval: 60 #default value (in seconds)
type: #optional指定限制(根据什么限制origin就是根据ip限制,这里可以设置好多参数,还可以根据http请求类型设置访问参数)
- origin
自定义类继承zuulfilter
import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.management.ObjectName;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
// 接口限流时:处理错误页面:通过配置把springboot本身的
// senderror处理错误页面的类,将其禁用,使用我们自定义的错误页面或者(我们想要返回一个json的数据)
@Component
public class ErrorResponseJSONFilter extends ZuulFilter {
@Value("${error.path:/error}")
private String errorPath;
public ErrorResponseJSONFilter() {
}
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
RequestContext currentContext = RequestContext.getCurrentContext();
return currentContext.getThrowable() !=null && !currentContext.getBoolean("sendErrorFilteer.ran",false);
}
@SneakyThrows
@Override
public Object run() throws ZuulException {
// 响应一个json的数据{code:429,msg:频繁访问}
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletResponse response = currentContext.getResponse();
// 刷新过于频繁才抛出异常
Map<String, Object> map = new HashMap<>();
// rateLimitExceeded 本身springboot捕获的这个东西异常的.若我们捕获了它,就代表抛异常了
// 若捕获了rateLimitExceeded参数(springcloud底层就是rateLimitExceeded参数写死的) 就为true了,开始抛异常
if ("true".equals(currentContext.get("rateLimitExceeded"))) {
map.put("code","429");
map.put("msg","你太快了,慢点");
}else {
map.put("code","500");
map.put("msg","系统繁忙");
}
// 指定响应头信息,要不然没办反响应json格式信息
response.setContentType("text/json;charset=utf-8");
// 响应给浏览器
response.getWriter().write(JSON.toJSONString(map));
currentContext.setSendZuulResponse(false);
return null;
}
}