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

无登录系统下,如何为MERN Stack REST API端点实现安全防护?

无登录场景下API端点的专属访问实现方案

一、静态API密钥方案

这是最直接的适配方案,完全不需要登录体系:

  • 生成一个高复杂度的静态密钥(比如用openssl rand -hex 16生成32位随机字符串),绝对不要硬编码在前端源码里,通过构建工具的环境变量注入(比如Vite的VITE_API_KEY、Create React App的REACT_APP_API_KEY)。
  • 后端逻辑:要求所有API请求的请求头(比如X-API-Key)必须携带该密钥,收到请求后先校验密钥匹配性,不匹配直接返回403。
  • 后端示例(Node.js/Express):
const VALID_API_KEY = process.env.API_KEY; // 从后端环境变量读取,避免代码泄露

app.use((req, res, next) => {
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || apiKey !== VALID_API_KEY) {
    return res.status(403).send('无权访问');
  }
  next();
});
  • 注意事项:定期更换密钥;前端打包时要确保环境变量不会被轻易反编译(可做简单混淆);这种方式无法完全阻止恶意抓取,但能挡住绝大多数非针对性的访问。

二、请求签名验证方案(更安全)

比静态密钥更难伪造,还能防止重放攻击:

  • 前后端共享一个保密密钥(比如SECRET_KEY),同样通过环境变量注入,绝不硬编码。
  • 前端请求流程:
    1. 生成当前时间戳timestamp(用于限制请求有效期,比如5分钟,防止旧请求被重复提交)。
    2. 将请求路径、请求体(POST/PUT时)、时间戳拼接成字符串,用HMAC-SHA256算法生成签名signature。
    3. 把timestamp和signature放在请求头(比如X-Timestamp、X-Signature)里发送请求。
  • 后端验证流程:
    1. 检查时间戳是否在有效范围内,超出则直接拒绝。
    2. 用同样的规则拼接字符串并计算签名,和请求头里的签名对比,不一致则返回403。
  • 前端示例(浏览器环境用crypto-js):
import CryptoJS from 'crypto-js';

const SECRET_KEY = import.meta.env.VITE_SECRET_KEY;

function generateSignature(path, body, timestamp) {
  const payload = `${path}${JSON.stringify(body)}${timestamp}`;
  return CryptoJS.HmacSHA256(payload, SECRET_KEY).toString(CryptoJS.enc.Hex);
}

// 发起POST请求
const timestamp = Date.now().toString();
const signature = generateSignature('/api/student-grades', { studentId: 101, score: 95 }, timestamp);

fetch('/api/student-grades', {
  method: 'POST',
  headers: {
    'X-Timestamp': timestamp,
    'X-Signature': signature,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ studentId: 101, score: 95 })
});
  • 后端示例(Node.js/Express):
const crypto = require('crypto');
const SECRET_KEY = process.env.SECRET_KEY;
const MAX_TIME_DIFF = 5 * 60 * 1000; // 允许的最大时间差(5分钟)

app.use(express.json()); // 先解析请求体

app.use((req, res, next) => {
  const timestamp = req.headers['x-timestamp'];
  const signature = req.headers['x-signature'];
  const path = req.path;
  const body = req.body;

  // 验证时间戳有效性
  if (!timestamp || Date.now() - parseInt(timestamp) > MAX_TIME_DIFF) {
    return res.status(403).send('请求已过期');
  }

  // 重新计算签名
  const payload = `${path}${JSON.stringify(body)}${timestamp}`;
  const computedSignature = crypto.createHmac('sha256', SECRET_KEY)
    .update(payload)
    .digest('hex');

  if (!signature || computedSignature !== signature) {
    return res.status(403).send('签名验证失败');
  }
  next();
});

三、IP白名单补充方案

如果你的前端和后端部署在固定IP的服务器上,可以配合IP白名单进一步限制访问:

  • 比如在Nginx反向代理里配置:
location /api/ {
  allow 123.45.67.89; # 你的前端服务器IP
  allow 10.0.0.0/24; # 内部服务器IP段
  deny all;
}
  • 这个方案适合部署环境固定的场景,和令牌/签名方案结合使用,安全性翻倍。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:20:34