API 接口安全防护实战:鉴权、限流与防滥用配置完整指南

导语

很多网站的 Web 页面防护做得不错,API 接口却长期”裸奔”:没有鉴权、没有限流、参数不做校验。攻击者不需要攻破后台,只需要找到几个未鉴权的接口,就能批量刷单、遍历数据、薅羊毛、拖库。今天这篇教程,从攻击面分析到 Nginx 层限流、签名鉴权落地,帮你把 API 接口的安全水位拉到及格线以上,全部配置可直接复制。

一、先看清 API 的三大攻击面

  • 未授权访问:接口不校验身份,任何人拿着 URL 就能调用,典型如遍历用户 ID 拉取全部资料;
  • 参数注入与滥用:数值不校验导致负数下单、批量遍历、恶意超大分页拖库;
  • 无频率限制:没有限流,攻击脚本可以并发刷爆接口,既薅资源又拖垮后端,本质就是 CC 攻击。

下面按”入口限流 → 身份鉴权 → 参数校验 → 日志审计”四步,把防线一条条立起来。

二、Nginx 层限流:先把入口闸门焊死

限流是 API 防护的第一道闸,成本最低、见效最快。以 Nginx 为例,用 limit_req 做令牌桶限速,按 IP 维度限制每秒请求数:

http {
    # 定义限流区域:每个 IP 每秒 5 次,超出部分按 10 次/秒 的速度排队(burst)
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;

    server {
        location /api/ {
            limit_req zone=api_limit burst=10 nodelay;
            # 单 IP 并发连接数限制
            limit_conn_zone $binary_remote_addr zone=api_conn:10m;
            limit_conn api_conn 20;
            # 限制请求体大小,防止上传型滥用
            client_max_body_size 2m;
            # 只允许指定请求方法
            if ($request_method !~ ^(GET|POST|PUT|DELETE)$) {
                return 405;
            }
        }
    }
}

配置生效后立即验证:nginx -t && nginx -s reload,然后用 ab -n 200 -c 50 https://你的域名/api/demo 压测,能看到大量 503 说明限流已生效。对登录、发短信等敏感接口,建议单独加更严的规则,例如短信接口每 IP 每分钟 1 次。

三、身份鉴权:签名校验 + Token 双保险

限流只能挡”量”,挡不住”合法身份滥用”。生产环境推荐「Token 会话 + 请求签名」双层鉴权:Token 确认你是谁,签名确认请求没被篡改。以 Python Flask 为例:

import hashlib, hmac, time

SECRET_KEY = "请替换为随机生成的密钥"

def verify_sign(token, timestamp, sign, params):
    # 1. 时间戳防重放:超过 300 秒直接拒绝
    if abs(int(time.time()) - int(timestamp)) > 300:
        return False
    # 2. 参数按字典序拼接后加盐签名
    raw = "&".join(f"{k}={params[k]}" for k in sorted(params))
    expect = hmac.new(SECRET_KEY.encode(), (raw + token).encode(),
                      hashlib.sha256).hexdigest()
    # 3. 使用 hmac.compare_digest 防时序攻击
    return hmac.compare_digest(expect, sign)

校验要点:时间戳窗口防止重放攻击,字典序拼接防止参数顺序干扰签名,compare_digest 防止通过响应耗时猜签名。同时 Token 必须设置过期时间,权限过大或泄露时通过管理后台一键吊销。

四、参数校验与权限控制:最后一公里

1. 白名单校验,拒绝一切意外

所有入参必须走白名单:类型、长度、取值范围逐项核对,非法输入一律 400 返回,而不是让参数流向后端:

# 分页参数示例:page 必须是 1~10000 的整数,size 固定 1~100
def validate_page(page, size):
    if not str(page).isdigit() or not (1 <= int(page) <= 10000):
        return False
    if not str(size).isdigit() or not (1 <= int(size) <= 100):
        return False
    return True

2. 数据权限:永远校验”能不能看这条数据”

横向越权是接口漏洞重灾区:用户 A 的接口必须校验资源归属,绝不能仅凭传入的 ID 直接返回数据。核心原则:先校验归属,再返回数据

五、日志审计与异常告警

接口安全必须”看得见”。在 Nginx access 日志中单独记录 API 请求,并接入监控:

log_format api_log '$remote_addr [$time_local] "$request" $status '
                   '$body_bytes_sent "$http_user_agent" $request_time';
server {
    location /api/ {
        access_log /var/log/nginx/api_access.log api_log;
    }
}

# 定时统计 5 分钟内单 IP 请求量,超过阈值自动加入黑名单
awk '{print $1}' /var/log/nginx/api_access.log | sort | uniq -c \
  | sort -rn | head -20

建议重点盯三类信号:高频 401/403(有人在撞鉴权)、超大响应体(可能被批量拉数据)、非业务时段的请求峰值(脚本在跑)。配合 fail2ban,对触发阈值的 IP 自动封禁 24 小时。

总结

API 安全不是装一个 WAF 就完事,而是”限流、鉴权、校验、审计”四层缺一不可:Nginx 限流挡住流量洪峰,签名 Token 拦住伪造请求,白名单校验掐掉注入与越权,日志告警让攻击无处遁形。对接口数量多、又不想逐个手写防护逻辑的团队,建议直接在网关层统一防护——速度网络提供高防 CDN 与云 WAF 服务,自带 CC 防护、源站隐藏和恶意请求拦截,能在一层就把绝大部分接口滥用挡在外面,源站只需专注业务逻辑。接口安全,从今天开始补齐四层防线。

给TA打赏
共{{data.count}}人
人已打赏
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
在线客服
在线客服
热线电话
QQ客服
电子邮箱
suduwangluo