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

如何保障React+Express架构下客户端HTTP接口调用的安全性?

防止无关人员访问Express API的最佳方案

你之前直接在前端携带API密钥的方式确实不可行,因为前端代码和请求头都能被轻易查看。下面是几种适合你场景的可靠方案:

1. 用户身份认证(核心方案)

通过登录机制识别合法用户,只有认证通过的用户才能访问API,最常用的是JWT(JSON Web Token):

客户端实现(React + Axios)

登录成功后将后端返回的token存在内存或安全的存储中,后续请求自动携带:

// 登录示例
async function login(username, password) {
  const res = await axios.post(`${backendDomain}/login`, { username, password });
  // 将token存在内存(比如React Context或状态管理工具),避免存localStorage防止XSS
  window.__authToken = res.data.token;
}

// 请求API时携带token
async function getData(id){
  try {
    const res = await axios.get(`${backendDomain}/data/${id}`, {
      headers: {
        'Authorization': `Bearer ${window.__authToken}`
      }
    });
    return res.data;
  } catch (error) {
    // 处理认证失败,比如跳转登录页
  }
}

服务器端实现(Express)

添加JWT验证中间件,只有token合法才允许访问API:

const jwt = require('jsonwebtoken');
const secretKey = process.env.JWT_SECRET; // 私钥存在环境变量,不要硬编码

// JWT验证中间件
function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];
  
  if (!token) return res.sendStatus(401);

  jwt.verify(token, secretKey, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
}

// 登录接口,生成token
app.post('/login', (req, res) => {
  // 验证用户名密码逻辑(比如查数据库)
  const validUser = checkUser(req.body.username, req.body.password);
  if (!validUser) return res.sendStatus(401);

  const token = jwt.sign({ userId: validUser.id }, secretKey, { expiresIn: '1h' });
  res.json({ token });
});

// 受保护的API,添加验证中间件
app.get('/data/:id', authenticateToken, function(req, res) {
  // 这里可以用req.user获取用户信息,返回该用户有权限的数据
  const data = fetchData(req.params.id, req.user.userId);
  res.send(data);
});

2. 会话验证(适合传统场景)

如果不想用JWT,可以用Express会话机制,依赖浏览器的cookie(需配置HttpOnly和Secure属性防止XSS):

服务器端配置

const session = require('express-session');
const cookieParser = require('cookie-parser');

app.use(cookieParser());
app.use(session({
  secret: process.env.SESSION_SECRET, // 会话密钥存在环境变量
  resave: false,
  saveUninitialized: false,
  cookie: { 
    httpOnly: true, // 禁止前端JS访问cookie
    secure: process.env.NODE_ENV === 'production', // 生产环境仅HTTPS传输
    maxAge: 3600000 // 1小时有效期
  }
}));

// 登录接口
app.post('/login', (req, res) => {
  const validUser = checkUser(req.body.username, req.body.password);
  if (!validUser) return res.sendStatus(401);
  
  req.session.userId = validUser.id;
  res.sendStatus(200);
});

// 验证会话的中间件
function checkSession(req, res, next) {
  if (!req.session.userId) return res.sendStatus(401);
  next();
}

// 受保护的API
app.get('/data/:id', checkSession, function(req, res) {
  const data = fetchData(req.params.id, req.session.userId);
  res.send(data);
});

客户端无需额外处理cookie,浏览器会自动在请求中携带会话cookie。

3. 请求签名(适合敏感操作)

对于需要更高安全性的接口,可以结合认证+请求签名,防止请求被篡改或重放:

  • 客户端登录后,后端返回JWT和临时签名密钥(仅存在内存)
  • 每次请求时,用密钥对请求路径、参数、当前时间戳做HMAC-SHA256签名,放在X-Signature头
  • 服务器验证签名的正确性,同时检查时间戳是否在有效期内(比如5分钟),防止重放攻击

4. 辅助防护措施

严格CORS配置

限制只有你的前端域名能跨域请求API,防止其他网站恶意调用:

const cors = require('cors');
app.use(cors({
  origin: 'https://你的前端域名.com', // 只允许你的前端域名
  credentials: true // 允许携带cookie或token
}));

注意:CORS是浏览器层面的限制,无法阻止Postman等工具直接调用,必须结合认证方案。

速率限制

用express-rate-limit防止暴力请求:

const rateLimit = require('express-rate-limit');
const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分钟
  max: 100 // 每个IP最多100次请求
});
app.use('/data/', apiLimiter);

强制HTTPS

生产环境必须启用HTTPS,防止请求被窃听或篡改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:20:40