You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js后端如何实现仅单次生效的唯一API接口 防范数据爬取与泄露

单次有效API实现方案

核心逻辑

通过为每个API请求绑定一次性失效的唯一Token,将Token作为API路径的一部分,结合高性能KV存储实现单次访问校验,从根源上避免用户通过修改参数批量爬取数据。

具体实现步骤

  • 服务端生成带签名的唯一Token:用户访问视频页面时,服务端生成UUID作为基础Token,将Token与对应视频资源ID、过期时间绑定,通过HMAC算法生成签名防止用户伪造Token,最终生成的完整Token同时存入Redis等KV数据库,设置5-10分钟的自动过期时间,避免无效数据占用存储。
  • 改造API路径规则:将原有带资源参数的API(例如/api/video?id=xxx)改为携带Token的路径形式(例如/api/video/{完整Token}),确保每个API地址都是唯一值。
  • 请求校验逻辑开发:用户请求带Token的API时,首先查询KV数据库中是否存在对应Token:
    • 若Token不存在(已使用/过期/伪造),直接返回null
    • 若Token存在,立刻删除该Token保证仅可使用一次,校验Token签名合法性后返回对应视频资源数据
  • 页面刷新适配:用户刷新页面时,服务端会重新生成新的Token并下发,对应新的API地址仍仅支持单次访问。

可选优化点

  • 增加IP级别的页面请求限流,防止攻击者批量刷页面获取大量有效Token爬取数据
  • 若后续需要支持非公开资源,可将用户身份标识也绑定到Token签名规则中,避免Token被转发盗用
  • 前端渲染时直接将API地址注入到页面逻辑中,不要暴露Token生成与拼接规则,降低被逆向的风险

Node.js 示例代码(基于Express + Redis)

const express = require('express');
const Redis = require('ioredis');
const { v4: uuidv4 } = require('uuid');
const crypto = require('crypto');

const app = express();
const redis = new Redis();
// 业务签名密钥,生产环境需存入环境变量避免泄露
const SIGN_SECRET = process.env.API_SIGN_SECRET || 'your_custom_secure_secret';

// 模拟业务逻辑:根据视频ID取视频数据
const getVideoInfoById = async (videoId) => {
  return {
    id: videoId,
    url: 'https://your-video-cdn-address/xxx.mp4',
    title: '示例视频标题'
  };
};

// 视频页面路由:下发带Token的API地址
app.get('/video/:videoId', async (req, res) => {
  const { videoId } = req.params;
  const rawToken = uuidv4();
  // 生成签名防止Token被伪造篡改
  const sign = crypto.createHmac('sha256', SIGN_SECRET)
    .update(`${rawToken}:${videoId}`)
    .digest('hex');
  const fullToken = `${rawToken}.${sign}`;
  // Token存入Redis,有效期5分钟
  await redis.set(`api:token:${fullToken}`, videoId, 'EX', 300);
  // 渲染页面时将API地址注入,前端直接调用该地址即可
  res.render('video', {
    videoApi: `/api/video/${fullToken}`
  });
});

// 实际视频数据接口
app.get('/api/video/:token', async (req, res) => {
  const { token } = req.params;
  const tokenKey = `api:token:${token}`;
  // 查询Token是否存在,同时直接删除保证仅可调用一次
  const videoId = await redis.getDel(tokenKey);
  if (!videoId) {
    return res.json(null);
  }
  // 校验签名合法性
  const [rawToken, sign] = token.split('.');
  const validSign = crypto.createHmac('sha256', SIGN_SECRET)
    .update(`${rawToken}:${videoId}`)
    .digest('hex');
  if (sign !== validSign) {
    return res.json(null);
  }
  // 返回业务数据
  const videoData = await getVideoInfoById(videoId);
  res.json(videoData);
});

app.listen(3000, () => {
  console.log('service start at port 3000');
});

内容的提问来源于stack exchange,提问作者Kien Pham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 20:15:03