使用redis计数来控制单位时间内对某接口的访问量,防止刷验证码接口之类的
来源:互联网 发布:用windows 2000的电脑 编辑:程序博客网 时间:2024/05/20 07:19
使用自定义注解的方式,在需要被限制访问频率的方法上加注解即可控制。
看实现方式,基于springboot,aop,redis。
新建Springboot工程,引入redis,aop。
创建注解
package com.tianyalei.annotation;import org.springframework.core.Ordered;import org.springframework.core.annotation.Order;import java.lang.annotation.*;/** * Created by wuwf on 17/7/6. */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documented//最高优先级@Order(Ordered.HIGHEST_PRECEDENCE)public @interface RequestLimit { /** * 允许访问的次数 */ int count() default 5; /** * 时间段,多少时间段内运行访问count次 */ long time() default 60000;}
Aspect切面处理逻辑
package com.tianyalei.aspect;import com.tianyalei.annotation.RequestLimit;import com.tianyalei.util.HttpRequestUtil;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 org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.util.concurrent.TimeUnit;/** * Created by wuwf on 17/7/6. */@Component@Aspectpublic class RequestLimitAspect { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private RedisTemplate<String, String> redisTemplate; @Before("execution(public * com.tianyalei.controller.*.*(..)) && @annotation(limit)") public void requestLimit(JoinPoint joinpoint, RequestLimit limit) { // 接收到请求,记录请求内容 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); String ip = HttpRequestUtil.getIpAddr(request); String url = request.getRequestURL().toString(); String key = "req_limit_".concat(url).concat(ip); //加1后看看值 long count = redisTemplate.opsForValue().increment(key, 1); //刚创建 if (count == 1) { //设置1分钟过期 redisTemplate.expire(key, limit.time(), TimeUnit.MILLISECONDS); } if (count > limit.count()) { logger.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]"); throw new RuntimeException("超出访问次数限制"); } }}
获取IP的工具类
package com.tianyalei.util;import javax.servlet.http.HttpServletRequest;import java.net.InetAddress;import java.net.UnknownHostException;/** * Created by admin on 17/7/6. */public class HttpRequestUtil { /** * 获取当前网络ip * * @param request * @return */ public static String getIpAddr(HttpServletRequest request) { String ipAddress = request.getHeader("x-forwarded-for"); if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("Proxy-Client-IP"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("WL-Proxy-Client-IP"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getRemoteAddr(); if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) { //根据网卡取本机配置的IP InetAddress inet = null; try { inet = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); } ipAddress = inet.getHostAddress(); } } //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 if (ipAddress != null && ipAddress.length() > 15) { //"***.***.***.***".length() = 15 if (ipAddress.indexOf(",") > 0) { ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); } } return ipAddress; }}
通过Controller验证
@RestControllerpublic class IndexController { @RequestLimit(count = 4) @GetMapping("/index") public Object index() { return 1; }}启动工程,多次访问index看看效果即可。
阅读全文
2 0
- 使用redis计数来控制单位时间内对某接口的访问量,防止刷验证码接口之类的
- 防止频繁刷验证码接口-luosimao
- 使用python统计csdn博客一段时间内的访问量
- php + redis 完成api接口的图形验证码
- redis 对基本数据类型的处理接口
- 接口的认证,访问量,频率的统计
- 对Com接口的使用
- 使用perl统计日志中单位时间内的请求数
- 防止被刷接口的方法
- Androi的使用WireShark来调试接口
- AXI_DATAMOVER的控制接口
- 对接口使用的疑惑 接口“实例化”分析
- Android 2.3网络访问时,使用Authorization字段对接口加验证的问题
- ListView指定单位时间内的滚动距离
- 对接口的理解
- 对接口的理解
- 对接口的理解
- 对接口的理解
- golang 并发
- Android Material Design 中的CorrdinatorLayout使用详解
- 使用注解改进代码检查
- celery配置使用
- C++模板类成员函数最好和模板类声明一起放在同一个.h头文件里
- 使用redis计数来控制单位时间内对某接口的访问量,防止刷验证码接口之类的
- idea 常用代码提示设置
- avalon中的模板绑定(ms-include)
- 2017.7.6
- Nod-最长公共子序列Lcs(动态规划)
- oracle数据库导入导出命令
- Java[探索](三)移位操作符
- REST简介
- RxJava 2.x 教程(完结版)