SpringBoot + Nginx 免鉴权接口安全防护方案

一、核心风险说明

免鉴权接口(登录、验证码、注册、健康检查、公开查询等)无 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 关键字,定义速率限制
10r 10 个请求(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 限流,限流失效
相关推荐
中科岩创2 小时前
宁波某大学高支模施工安全监测实训模型应用
科技·物联网·安全·自动化
翼龙云_cloud2 小时前
阿里云国际代理商:阿里云 ECS 全维度监控配置教程
运维·阿里云·云计算·监控
笑锝没心没肺2 小时前
fail2ban工具安装配置及使用
linux·运维·服务器
项目经理老王3 小时前
OpenClaw无捆绑安装包,安全纯净版AI助手部署
人工智能·安全
zt1985q3 小时前
本地部署开源智能家居集成平台 ioBroker 并实现外部访问( Windows 版本)
运维·服务器·智能家居
大卡片4 小时前
linux内核驱动开发
linux·运维·驱动开发
心心喵5 小时前
[linux] nohup和pm2的区别 进程保活
linux·运维·服务器
NGINX开源社区6 小时前
F5 NGINX Ingress Controller 5.3.0 新增功能
运维
SelectDB7 小时前
Apache Doris 在 AgentLogsBench 中领先,支撑 Agent 可观测性生产负载
运维·数据库·agent