Java接口访问限制次数(使用IP作为唯一标识)

这篇具有很好参考价值的文章主要介绍了Java接口访问限制次数(使用IP作为唯一标识)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java接口访问限制次数(使用IP作为唯一标识)

1、获取用户IP工具类

	/**
     * 获取ip地址
     */
    public static String getIp(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.getRemoteAddr();
        }
        String comma = ",";
        String localhost = "127.0.0.1";
        if (ip.contains(comma)) {
            ip = ip.split(",")[0];
        }
        if  (localhost.equals(ip))  {
            // 获取本机真正的ip地址
            try {
                ip = InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
        return ip;
    }

2、接口限制注解(切面)

(1)controller层
@LimitRequest(time = "${limit.request.time}", count = "${limit.request.count}", isFlag = true)
(2)注解类
import java.lang.annotation.*;

/**
 * @author liyanhua
 * @date 2022/12/14 10:17
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LimitRequest {
    // 限制时间 单位:分钟,这里默认1分钟
    String time() default "1";
    // 允许请求的次数
    String count() default "100";
    // 是否走配置文件,默认不走配置文件
    boolean isFlag() default false;
}
(3)切面方法
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * @author liyanhua
 * @date 2022/12/14 10:18
 */
@Aspect
@Component
public class LimitRequestAspect {

    private static final Logger logger = LoggerFactory.getLogger(LimitRequestAspect.class);

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final BeanExpressionContext exprContext;
    private final BeanExpressionResolver exprResolver;

    //=============通过配置的路径获取数据=========================开始
    public LimitRequestAspect(ConfigurableBeanFactory beanFactory) {
        this.exprContext = new BeanExpressionContext(beanFactory, (Scope)null);
        this.exprResolver = beanFactory.getBeanExpressionResolver();
    }
    public String resolveStringValue(String strVal) {
        String value = this.exprContext.getBeanFactory().resolveEmbeddedValue(strVal);
        if (this.exprResolver != null && value != null) {
            Object evaluated = this.exprResolver.evaluate(value, this.exprContext);
            value = evaluated != null ? evaluated.toString() : null;
        }
        return value;
    }
    //=============通过配置的路径获取数据=========================结束

    // 让所有有@LimitRequest注解的方法都执行切面方法
    @Pointcut("@annotation(limitRequest)")
    public void excudeService(LimitRequest limitRequest) {
    }

    @Around("excudeService(limitRequest)")
    public Object doAround(ProceedingJoinPoint pjp, LimitRequest limitRequest) throws Throwable {
        // 获得request对象
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        // 获取用户ip
        String ipStr = request.getHeader("x-forwarded-for");
        if (StringUtils.isBlank(ipStr) || "unknown".equalsIgnoreCase(ipStr)) {
            ipStr = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ipStr) || "unknown".equalsIgnoreCase(ipStr)) {
            ipStr = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ipStr) || "unknown".equalsIgnoreCase(ipStr)) {
            ipStr = request.getRemoteAddr();
        }
        // 获取用户id
        String userId = null;
        Object[] args = pjp.getArgs();
        for (Object arg : args) {
            if (arg instanceof DcbUserDTO) {
                DcbUserDTO dcbUserDTO = (DcbUserDTO) arg;
                userId = dcbUserDTO.getUserId();
            }
        }
        if (StringUtils.isBlank(userId)) {
            userId = request.getParameter("userId");
        }
        logger.info("===========切面获取的用户id:"+userId);

        // 不同接口的唯一标识key
        String key = StringUtils.join(request.getRequestURI(),"-",ipStr,"-",userId);
        logger.info("===========切面获取的唯一key:"+key);

        String redisValue = redisTemplate.opsForValue().get(key);
        Integer count = 0;
        if (StringUtils.isNotBlank(redisValue)){
            count = JSON.parseObject(redisValue, Integer.class);
        }

        // 总次数
        Integer totalCount;
        // 时间间隔
        Long time;
        if (limitRequest.isFlag()){
            totalCount = Integer.valueOf(this.resolveStringValue(limitRequest.count()));
            time = Long.valueOf(this.resolveStringValue(limitRequest.time()));
        }else {
            totalCount = Integer.valueOf(limitRequest.count());
            time = Long.valueOf(limitRequest.time());
        }

        if (count >= totalCount){
            return ResultDTO.failure("接口访问次数超过限制,请"+time+"分钟后重试");
        } else if (count == 0){
            redisTemplate.opsForValue().set(key,JSON.toJSONString(1), time, TimeUnit.MINUTES);
        } else {
            // 加1
            redisTemplate.opsForValue().increment(key);
        }

        // result的值就是被拦截方法的返回值,执行业务方法
        Object result = pjp.proceed();

        return result;
    }

}

文章来源地址https://www.toymoban.com/news/detail-549847.html

到了这里,关于Java接口访问限制次数(使用IP作为唯一标识)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Golang实现HTTP代理突破IP访问限制

    在当今互联网时代,网站和服务商为了维护安全性和保护用户隐私,常常会对特定的IP地址进行封锁或限制。但是,有时候我们可能需要访问这些被限制的网站或服务。为了突破这种限制,我们可以使用HTTP代理来隐藏真实的客户端IP地址,从而绕过限制。 本文将介绍如何使用

    2024年02月07日
    浏览(42)
  • nginx 每天各IP访问次数记录统计

    此文章主要介绍了,在nginx代理的情况下,统计当天IP的出现次数,并且生成表格的相关步骤 1.nginx 配置的修改 在/etc/nginx/nginx.conf 2.定时执行的shell脚本 该脚本主要在每天的0点自动执行IPStatistics.py来记录昨天的IP访问次数,然后对昨天的日志进行备份,并且备份最长时间为m

    2024年02月12日
    浏览(39)
  • SpringBoot后端统计网站的IP访问次数及地区

             项目是用SpringBoot+Vue实现,前后端分离的,前端是用nginx部署的,虽说可以通过Nginx的日志来统计网站的IP的访问次数,但想在前端用图形化的方式来展示是不太可行的,所以我想着是在SpringBoot后端来实时统计访问的网站的IP及其次数和地区,然后存储在数据库中,前

    2023年04月08日
    浏览(45)
  • 限制API接口访问速率

    免责声明:本人无意侵权,奈何找不到原文作者,也找不到网址,于是自己记录一下,如果有侵权之嫌,请联系我删除文章

    2024年01月19日
    浏览(43)
  • tomcat限制IP访问

    tomcat可以通过增加配置,来对来源ip进行限制,即只允许某些ip访问或禁止某些来源ip访问。 配置路径:server.xml 文件下 标签下。与同级 此处标签尽量通过复制同级标签后修改进行,因为使用的是Valve,而不是Value,防止手敲导致错误 allow:允许访问的ip,支持正则表达 deny:拒

    2024年02月12日
    浏览(41)
  • 如何限制 IP 多次重新访问

    随着互联网的快速发展,网络安全问题日益突出。恶意 IP 多次重新访问是一种常见的手段,可能导致服务器负载过高、资源浪费、网站响应速度下降等问题。为了提高网络安全性,我们需要采取有效的措施来限制恶意 IP 的多次重新访问。下面简单的介绍几点来帮助您。 使用

    2024年01月24日
    浏览(54)
  • Easy IP(出接口公网IP地址作为NAT转换)

    1、Easy IP。         Easy IP是一种利用出接口的公网IP地址作为NAT转后的地址,同时转换地址和端口的地址转换方式。对于接口IP是动态获取的场景,Easy IP也一样支持。         当FW的公网接口通过拨号方式动态获取公网地址时,如果只想使用这一个公网IP地址进行地址转

    2024年04月13日
    浏览(43)
  • iptables 限制所有ip访问22端口,仅开放个别ip访问 持续更新

    查看当前iptables 规则 添加已经建立tcp连接,就开放网络访问 添加允许访问22端口的ip 拒绝所有ip访问22端口 新加一个ip访问该主机22端口 保存iptables规则 参数详解 效果 本文参考:https://blog.csdn.net/zhougubei/article/details/120350467 本文参考:https://blog.csdn.net/qq_44273583/article/details/116661

    2024年02月07日
    浏览(49)
  • IP代理安全吗?如何防止IP被限制访问?

    你是否遇到过可以正常上网,但访问某个网站却被禁止?注册某个网站账号,却被封号?那都是因为IP出现问题!您的IP地址透露很多关于您的信息,包括您的位置和互联网活动。 在本文中,我们将一起了解IP地址,网站如何利用它来跟踪您,以及与IP代理如何帮助您更好的推

    2024年02月07日
    浏览(52)
  • 如何通过openresty 限制国外Ip访问

    参考代码 首先 需要的依赖: libmaxminddb 需要 gcc 编译,可用 Dockerfile 里面编译生成so文件,然后复制到 openresty/openresty:centos-rpm 镜像中,然后把 Country.mmdb (Ip数据库) 也复制到镜像中 Dockerfile 如下: 然后配置lua脚本,OpenResty(也称为 ngx_openresty)是一个基于 Nginx 与 Lua 的高性

    2024年02月01日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包