基于SpringBoot+Nginx实现免鉴权接口安全防护方案

 更新时间:2026年07月07日 09:12:08   作者:xixingzhe2  
本文围绕SpringBoot与Nginx协同防护免鉴权接口(如登录、验证码、注册等)展开,提出三层防护体系:Nginx层实现IP限流、黑名单封禁、参数过滤、真实IP校验及人机校验前置拦截,需要的朋友可以参考下

一、核心风险说明

免鉴权接口(登录、验证码、注册、健康检查、公开查询等)无 token 校验,常见攻击:

  1. 暴力 破解(登录密码 / 验证码爆破)
  2. 高频刷接口(短信轰炸、注册灌水、DoS)
  3. SQL 注入、XSS、路径遍历
  4. 爬虫批量拉取公开数据
  5. IP 恶意请求、CC 攻击
  6. 越权、参数篡改、重放攻击

防护分三层:Nginx 层前置拦截(低成本、高性能) + SpringBoot 应用层校验(业务逻辑防护) + 基础设施兜底。

二、Nginx 层防护(优先做,不占用 Java 服务资源)

1. 单 IP 限流,防高频刷接口(CC / 短信轰炸)

对所有免登接口单独配置限流,区分普通接口 / 验证码 / 登录接口(验证码限流更严)

# 全局限流配置 http块
http {
    # 按IP限流,10M内存存储IP
    limit_req_zone $binary_remote_addr zone=free_api:10m rate=10r/s;
    # 验证码单独限流,更严格
    limit_req_zone $binary_remote_addr zone=code_api:10m rate=1r/3s;
    # 登录接口限流
    limit_req_zone $binary_remote_addr zone=login_api:10m rate=2r/m;
}
server {
    location /api/login {
        limit_req zone=login_api burst=3 nodelay;
        proxy_pass http://springboot;
    }
    location /api/sendCode {
        limit_req zone=code_api burst=1 nodelay;
    }
    # 所有免鉴权接口统一限流
    location ~ ^/api/(public|register|health) {
        limit_req zone=free_api burst=5 nodelay;
        proxy_pass http://springboot;
    }
}

参数说明:

  • $binary_remote_addr:这是 Nginx 的一个内置变量,表示客户端的 IP 地址(二进制格式)。
  • zone=free_api:10m:定义一个名为 free_api 的共享内存区域,大小为 10 MB。
  • rate=1r/3s:每 3 秒最多 1 次请求
  • burst:突发缓冲队列,超出直接返回 503
  • nodelay:队列请求立即处理,不延迟排队

1.1 zone=free_api:10m

部分说明
zone关键字,表示定义一块共享内存区域
free_api自定义名称,在后续 limit_req 指令中引用它
10m内存大小为 10 MB(m 代表兆字节)

内存能存储多少数据?

  • Nginx 使用高效的哈希表存储每个 IP 的访问状态
  • 每个 IP 大约占用 32-64 字节
  • 10 MB ≈ 能存储 15万-30万个 不同的 IP 地址
  • 当内存用满时,Nginx 会移除最旧的记录(LRU 策略)。如果日活用户 100万,这会导致旧的IP记录被频繁淘汰,限流失效。

选择多大内存合适?

# 小型业务(日活 < 1万)
zone=free_api:1m
# 中等业务(日活 1万-50万)
zone=free_api:10m
# 大型业务(日活 > 50万)
zone=free_api:50m

1.2 rate=10r/s

部分说明
rate关键字,定义速率限制
10r10 个请求(r = request)
/s每秒(per second),也可以使用 /m(每分钟)

常用速率示例

# 每秒 1 个请求(适合防止暴力 破解登录接口)
rate=1r/s;
# 每分钟 60 个请求(等价于每秒1个,但允许突发)
rate=60r/m;
# 每秒 100 个请求(适合高并发公开API)
rate=100r/s;

重要概念:速率是如何计算的?

  • 基于 令牌桶算法(Token Bucket)
  • Nginx 会以固定速率(每秒 10 个)往桶中添加令牌
  • 每个请求需要消耗 1 个令牌
  • 令牌耗尽后,新请求会被延迟或拒绝

2. IP 黑名单 + 临时封禁(爆破拦截)

配合限流自动拉黑恶意 IP,使用 nginx lua/deny,或定时脚本同步攻击 IP

# 封禁恶意IP列表
deny 192.168.1.100;
# 允许内网
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;

3. 请求参数过滤,拦截注入攻击

Nginx 匹配 URL / 参数关键字,拦截 SQL 注入、XSS、路径遍历

if ($query_string ~* "union|select|and|or|alert|<script>|../") {
    return 403;
}
# 拦截异常请求方法
if ($request_method !~ ^(GET|POST)$ ) {
    return 405;
}
# 限制请求体大小,防大报文DoS
client_max_body_size 10k;

4. 伪造 IP 防护(必须配置,避免黑客伪造 X-Forwarded-For 绕过限流)

如果前端有 CDN / 负载均衡,正确取真实客户端 IP,防止伪造 IP 无限刷接口:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 信任CDN内网IP,防止伪造XFF
real_ip_header X-Forwarded-For;
set_real_ip_from 10.0.0.0/8;

5. 验证码 / 登录接口增加人机校验拦截

Nginx 拦截无验证码、无滑块票据的请求,结合前端传入captchaId参数校验,无则 403。

6. 关闭敏感头、防信息泄露

server_tokens off; # 隐藏nginx版本
proxy_hide_header Server;
add_header X-Frame-Options DENY;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;

三、SpringBoot 应用层防护(业务级安全,Nginx 挡不住的恶意请求)

1. 接口粒度区分免鉴权路径(统一拦截器 / 过滤器)

使用 Spring Security / 自定义 Filter,白名单放行免登接口,其余强制 token;禁止全局开放。

Spring Security 示例

@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(auth -> auth
                // 免鉴权白名单
                .requestMatchers("/api/login", "/api/sendCode", "/api/public/**", "/actuator/health").permitAll()
                // 其他全部需要认证
                .anyRequest().authenticated()
        );
        return http.build();
    }
}

2. 业务层限流(分布式场景,Nginx 单机限流失效补充)

使用 Redis 实现分布式 IP 限流,针对登录、验证码做次数限制:

  • 同一 IP 1 分钟最多 5 次登录失败,锁定 10 分钟
  • 同一手机号 1 分钟最多 1 条验证码,1 天上限 10 条

伪代码示例:

// 登录失败计数
String key = "login:fail:" + ip;
Long count = redisTemplate.opsForValue().increment(key, 1);
if(count == 1) redisTemplate.expire(key, 10, TimeUnit.MINUTES);
if(count > 5) return "登录过于频繁,请稍后再试";

3. 人机验证(核心防刷手段)

所有高危免登接口强制人机校验:

  1. 图形验证码(登录 / 注册)
  2. 滑块 / 行为验证码(极验、阿里云验证码)
  3. 设备指纹:前端采集浏览器指纹、UA、设备 ID 上传后台校验。

无合法验证码票据直接拒绝业务处理。

4. 请求参数强校验(防注入、越权)

使用 Hibernate Validator 全局校验所有入参:

  • 手机号、邮箱长度、格式正则校验
  • ID、数字参数限制数值范围
  • 禁止特殊字符、脚本标签传入
@PostMapping("/sendCode")
public Result sendCode(@NotBlank @Pattern(regexp = "^1[3-9]\\d{9}$") String phone) {
    // 业务逻辑
}

全局异常拦截非法参数请求,记录攻击日志。

5. 防重放攻击(公开查询接口)

给前端分配临时签名参数 timestamp + nonce + sign

  1. 前端用密钥对参数 + 时间戳加密生成 sign
  2. 后端校验:时间戳 5 分钟内有效、nonce 一次性存入 Redis 去重、sign 校验一致 防止抓包后重复调用免登接口拉取数据。

6. 敏感操作风控规则

  • 同一 IP 短时间大量注册账号 → 拒绝注册
  • 异地高频登录 → 二次验证
  • 批量查询接口增加分页上限,禁止一次性查全量数据

7. 全局异常日志 + 攻击记录

拦截所有 400、403、限流、参数非法请求,记录:IP、接口、参数、UA,定时统计恶意 IP 推送告警。

四、分布式 / 集群补充方案

  • Redis 分布式限流:多台 Nginx、多 SpringBoot 实例时,单机 Nginx 限流失效,统一用 Redis 存储 IP 访问计数。
  • CDN/WAF 前置防护:阿里云 WAF、Cloudflare 等云 WAF:内置 CC 防护、SQL 注入、爬虫识别、验证码拦截,最省心。
  • 接口灰度频次控制:公开数据接口 做分档 QPS 限制:普通访客低并发,登录用户放开额度。

五、不同免鉴权接口差异化防护策略

接口类型核心攻击防护重点
登录接口密码暴力 破解登录失败计数封禁、人机验证、IP 限流
短信验证码短信轰炸手机号 + IP 双重限流、每日上限
注册接口灌水批量注册设备指纹、滑块验证码、IP 频次
公开查询接口爬虫批量爬取签名防重放、分页限制、IP 限流
健康检查 / 监控扫描探测内网 IP 白名单,外网直接禁止访问

六、最简落地执行顺序

  • Nginx 配置 IP 限流、请求过滤、真实 IP 解析(第一层拦截)
  • SpringSecurity 严格配置免登白名单,杜绝越权开放接口
  • 登录 / 验证码接入人机验证码,增加 Redis 业务限流
  • 所有入参统一校验,增加时间戳签名防重放
  • 接入 WAF / 防火墙兜底,开启攻击日志告警
  • 定期清理、拉黑高频恶意 IP

七、常见踩坑点

  • 只在应用层限流,没做 Nginx 前置:大量无效请求打满 Java 线程池,服务雪崩
  • X-Forwarded-For 未正确配置,黑客伪造 IP 绕过限流
  • permitAll 配置 /**,误开放所有接口,造成越权漏洞
  • 验证码仅前端校验,后端不二次校验,黑客绕过前端直接调用接口
  • 单机 Nginx 集群部署,未做分布式 Redis 限流,限流失效

以上就是基于SpringBoot+Nginx实现免鉴权接口安全防护方案的详细内容,更多关于SpringBoot Nginx免鉴权接口安全防护的资料请关注脚本之家其它相关文章!

相关文章

  • java中判断map<String,List>是否有key的四种方法

    java中判断map<String,List>是否有key的四种方法

    这篇文章主要为大家详细介绍了java中判断map<String,List>是否有key的四种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-12-12
  • Spring createBeanInstance实例化Bean

    Spring createBeanInstance实例化Bean

    这篇文章主要为大家介绍了Spring createBeanInstance实例化Bean源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • 详解如何为SpringBoot Web应用的日志方便追踪

    详解如何为SpringBoot Web应用的日志方便追踪

    在Web应用程序领域,有效的请求监控和可追溯性对于维护系统完整性和诊断问题至关重要,SpringBoot是一种用于构建Java应用程序的流行框架,在本文中,我们探讨了在SpringBoot中向日志添加唯一ID的重要性,需要的朋友可以参考下
    2023-11-11
  • Java利用Netty时间轮实现延时任务

    Java利用Netty时间轮实现延时任务

    时间轮是一种可以执行定时任务的数据结构和算法。本文将为大家详细讲解一下Java如何利用Netty时间轮算法实现延时任务,感兴趣的小伙伴可以了解一下
    2022-08-08
  • Java输入数据的知识点整理

    Java输入数据的知识点整理

    在本篇文章里小编给大家整理的是关于Java如何输入数据的相关知识点内容,有兴趣的朋友们学习参考下。
    2020-01-01
  • Java Tree结构数据中查找匹配节点方式

    Java Tree结构数据中查找匹配节点方式

    这篇文章主要介绍了Java Tree结构数据中查找匹配节点方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java中synchronized用法汇总

    Java中synchronized用法汇总

    使用 synchronized 无需手动执行加锁和释放锁的操作,我们只需要声明 synchronized 关键字就可以了,JVM 层面会帮我们自动的进行加锁和释放锁的操作,我们今天重点来看一下synchronized 的几种用法
    2022-04-04
  • Mybatis全面分页插件

    Mybatis全面分页插件

    这篇文章主要为大家详细介绍了Mybatis全面分页插件的使用方法,比较适用于在分页时候进行拦截,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Ubuntu16.04安装部署solr7的图文详细教程

    Ubuntu16.04安装部署solr7的图文详细教程

    这篇文章主要为大家详细介绍了Ubuntu16.04安装部署solr7的图文详细教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • SpringBoot浅析安全管理之基于数据库认证

    SpringBoot浅析安全管理之基于数据库认证

    在真实的项目中,用户的基本信息以及角色等都存储在数据库中,因此需要从数据库中获取数据进行认证和授权
    2022-08-08

最新评论