Spring mvc通过访问者IP限制接口访问频率

https://blog.csdn.net/qq_31384551/article/details/80955215

我们有的时候系统里面有的用户接口为了控制访问频率,需要使用到,笔记走一波

环境:

spring

spring mvc

Guava:谷歌高并发工具,下面是maven

<!--谷歌guava高并发处理工具-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
我们这次主要使用到的是Guava工具的LoadingCache 和 

RateLimiter 即缓存和限流

 
由于是在spring 环境中,所以就直接上Service代码了:


/**
* 接口访问限流service,此接口主要用于针对ip地址对于接口访问的限流控制
*/
@Service
public class LoadingCacheServiceImpl implements LoadingCacheService {
LoadingCache<String, RateLimiter> ipRequestCaches = CacheBuilder.newBuilder()
.maximumSize(200)// 设置缓存个数
.expireAfterWrite(1, TimeUnit.DAYS)
.build(new CacheLoader<String, RateLimiter>() {
@Override
public RateLimiter load(String s) throws Exception {
return RateLimiter.create(0.2);// 新的IP初始化 (限流每秒0.1个令牌响应,即10s一个令牌)
}
});
public RateLimiter getRateLimiter(String key) throws ExecutionException {
return ipRequestCaches.get(key);
}
}
控制器使用代码:

@Controller
@RequestMapping("/tool/upload/")
public class FileUploadController{
@Resource
LoadingCacheService loadingCacheService;
/**
* ajax上传文件
* @param file 文件对象
* @return
*/
@RequestMapping("ajaxUpload")
@ResponseBody
public AjaxRes ajaxUpload(@RequestParam("file") MultipartFile file, HttpServletRequest httpServletRequest){
String ipAddr = IPUtil.getIpAddr(getRequest());
try {
RateLimiter limiter = loadingCacheService.getRateLimiter(ipAddr);
if(limiter.tryAcquire()){
//获得令牌(不限制访问)
}else {
//未获得令牌(限制访问)
}
} catch (ExecutionException e) {
e.printStackTrace();
}
return res;
}
}
注:主要就是把没一个用户IP的令牌桶RateLimiter给缓存起来,然后每次用户请求接口的时候就去拿一次令牌,那到令牌则不限制访问,没拿到则限制

PS:第一次使用,哪里不对请指正,谢谢

根据qq_35284533兄弟的提示,补充IPUtil工具类代码,这个工具类是用于获取IP地址的。

package com.jufanshare.myblog.common.util;

import javax.servlet.http.HttpServletRequest;

/**
* 获取客户端IP地址
*/
public class IPUtil {

/**
* 客户端真实IP地址的方法一:
*/
public static String getRemortIP(HttpServletRequest request) {
if (request.getHeader("x-forwarded-for") == null) {
return request.getRemoteAddr();
}
return request.getHeader("x-forwarded-for");
}
/**
* 客户端真实IP地址的方法二:
*/
public static String getIpAddr(HttpServletRequest request) {
String ip="";
if(request!=null){
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.getRemoteAddr();
}
}
return ip;
}
}
 

 
————————————————
版权声明:本文为CSDN博主「聚繁大BUG」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_31384551/article/details/80955215

原文地址:https://www.cnblogs.com/zhoading/p/12199780.html