黑马的登录模块加ip地址黑名单

    考虑一种场景,我们的短信发送接口被同一个人使用不同的手机号多次恶意调用,那么同样会导致之前说过的问题。
    要实现 IP 地址黑名单功能,核心是基于 IP 标识请求方,并通过 Redis 维护黑名单列表,结合拦截器在请求入口处校验。在redisconstants中
// ========== 新增【登录IP管控】核心配置 ==========
    // IP 1分钟限流Key(格式:verify:ip:limit:xxx.xxx.xxx.xxx):1IP1分钟仅能发1次验证码
    public static final String VERIFY_IP_LIMIT_KEY = "verify:ip:limit:";
    // IP请求次数统计Key(格式:verify:ip:count:xxx.xxx.xxx.xxx):统计短时间内IP总请求数
    public static final String VERIFY_IP_COUNT_KEY = "verify:ip:count:";
    // IP黑名单Key(格式:verify:ip:black:xxx.xxx.xxx.xxx):IP被封禁的标识
    public static final String VERIFY_IP_BLACK_KEY = "verify:ip:black:";
    // 通用过期时间(复用原有,无需新增):限流60s、统计1h、黑名单24h

在usersericeimpl中
//ip黑名单检测
        // 从session中获取HttpServletRequest对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // ====== 第一步:获取客户端真实IP(必须!适配本地/服务器/代理环境) ======
        String clientIp = getRealIp(request);
        // ====== 第二步:校验黑名单【优先级最高】 ======
        // 1. 校验IP是否在黑名单 → IP拉黑直接拒绝
        String ipBlackKey = RedisConstants.VERIFY_IP_BLACK_KEY + clientIp;
        if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(ipBlackKey))) {
            return Result.fail("ip在黑名单中!!");
        }
        // ====== 第三步:校验1分钟限流【防高频请求】 ======
        // 1. 校验IP:同一个IP,1分钟内仅能请求1次
        String ipLimitKey = RedisConstants.VERIFY_IP_LIMIT_KEY + clientIp;
        if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(ipLimitKey))) {
            return Result.fail("同一个IP,1分钟内仅能请求1次");
        }
        // 1. IP请求次数统计:短时间内超3次 → 拉黑IP
        String ipCountKey = RedisConstants.VERIFY_IP_COUNT_KEY + clientIp;
        Long ipCount = stringRedisTemplate.opsForValue().increment(ipCountKey);
        if (ipCount == 1) { // 首次请求,设置1小时过期
            stringRedisTemplate.expire(ipCountKey, RedisConstants.VERIFY_COUNT_TTL, TimeUnit.SECONDS);
        }

        // IP超3次 → 封禁IP(24小时)
        if (ipCount > 2) {
            stringRedisTemplate.opsForValue().set(ipBlackKey, "1", RedisConstants.VERIFY_BLACK_TTL, TimeUnit.SECONDS);

        }

 // ========== 工具方法1:获取客户端真实IP(关键!适配所有环境) ==========
    private String getRealIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 处理多代理场景,取第一个有效IP
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }

    // ========== 工具方法2:超阈值时,清理无用的限流/统计Key ==========
    private void cleanLimitKey(String... keys) {
        for (String key : keys) {
            stringRedisTemplate.delete(key);
        }
    }
全部评论

相关推荐

个人背景:学院二本计科专业 大二开始实习个人经历:安克创新 、理想汽车、字节跳动碎碎念:我做事只有三分钟热度。看到进了大厂的同学,我会羡慕,也会跟着努力上进;但遇到好看的小说,我又会放下手头的事沉迷其中,之前的坚持也就中断了。我有些自卑,总觉得自己学历和外貌都不够好。之前偶然在网上受到关注,我就喜欢上了上网,因为这里有很多人认可我。但我也很在意别人的评价,偶尔看到嘲讽的言论,会触发我的自卑情绪,让我感到愤怒。有时候我会强硬地回怼,有时候又会懦弱地选择无视。我也有虚荣心。不管是拿到安克、理想还是字节的机会,我在分享的时候都会带着这份心思。我会特意强调自己学历不好,是为了衬托出过程的艰难,以此显得自己更厉害。我知道,人往往会炫耀自己缺少的东西,来掩盖内心的空洞。我总想着走捷径,不太喜欢踏踏实实地做事。找实习的时候,我花了更多时间在研究面试技巧上,而不是提升专业能力。我会反复听面试录音分析技巧,看面试教程学习怎么和不同的面试官沟通,还会每天自言自语练习语言表达,同学都觉得我有点奇怪。我的实习生涯里,侥幸和运气占了很大一部分。我总在想,如果有一天我失去了这份幸运,这些特质可能会让我一蹶不振。ps: 很多人会问我学习路线和经验 但是就像我上面说的 我的实习过程靠的很多是关键节点的运气 技术上面我可能不如很多人  所以请大家理性求助和理性参考我的回答 附上我的投递记录
我的offer在哪里...:从去年看到现在,飞升哥就是榜样
我的求职进度条
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务