首页
学习
活动
专区
圈层
工具
发布

如何仅允许我的SPA调用公共rest API?

保护SPA调用的公共REST API的解决方案

基础概念

SPA(单页应用)调用公共REST API时面临的主要安全挑战是:由于前端代码完全暴露在客户端,传统的API密钥或凭证无法安全存储。需要采用特殊机制来确保只有你的SPA可以调用API,而其他客户端无法滥用。

解决方案

1. CORS (跨源资源共享)

原理:通过HTTP头部限制哪些源可以访问你的API

实现

代码语言:txt
复制
// Express示例
const express = require('express');
const app = express();

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'https://your-spa-domain.com');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});

优点

  • 简单易实现
  • 浏览器原生支持

缺点

  • 仅适用于浏览器环境
  • 无法防止直接API调用(如curl、Postman)

2. JWT (JSON Web Tokens) + 短期令牌

原理:后端颁发短期有效的JWT令牌,SPA在每次请求时携带

实现

代码语言:txt
复制
// 颁发令牌
const jwt = require('jsonwebtoken');
const token = jwt.sign({ client: 'spa' }, 'your-secret-key', { expiresIn: '15m' });

// 验证中间件
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, 'your-secret-key', (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
}

优点

  • 令牌可设置短期有效期
  • 无状态验证

缺点

  • 初始令牌仍需安全获取
  • 令牌泄露后仍可被滥用

3. 动态令牌 + 请求签名

原理:每次请求生成动态签名,防止重放攻击

实现

代码语言:txt
复制
// 前端请求签名
const crypto = require('crypto');

function signRequest(method, path, body, timestamp, secret) {
  const stringToSign = `${method}\n${path}\n${JSON.stringify(body)}\n${timestamp}`;
  return crypto.createHmac('sha256', secret).update(stringToSign).digest('hex');
}

// 后端验证
function verifyRequest(req, res, next) {
  const { signature, timestamp } = req.headers;
  const calculatedSig = signRequest(req.method, req.path, req.body, timestamp, 'your-secret');
  
  if (signature !== calculatedSig || Date.now() - timestamp > 300000) {
    return res.sendStatus(403);
  }
  next();
}

优点

  • 防止请求重放
  • 每个请求都唯一

缺点

  • 实现较复杂
  • 需要时间同步

4. 反向代理 + 请求头验证

原理:通过反向代理添加特殊请求头,API只接受带此头的请求

实现(Nginx配置)

代码语言:txt
复制
location /api {
  proxy_pass http://api-server;
  add_header X-Internal-Request "true";
}

# API服务器只接受带X-Internal-Request头的请求

优点

  • 完全隐藏API密钥
  • 前端无需处理认证

缺点

  • 需要基础设施支持
  • 代理本身需保护

5. 客户端证书认证

原理:为SPA部署客户端SSL证书

实现

代码语言:txt
复制
server {
  listen 443 ssl;
  ssl_client_certificate /path/to/ca.crt;
  ssl_verify_client on;
  
  location /api {
    if ($ssl_client_verify != SUCCESS) { return 403; }
    proxy_pass http://api-server;
  }
}

优点

  • 高安全性
  • 难以伪造

缺点

  • 证书管理复杂
  • 不适用于所有场景

最佳实践组合方案

  1. CORS限制:仅允许你的域名访问
  2. 短期JWT:初始通过安全端点获取短期令牌
  3. 请求签名:重要操作使用动态签名
  4. 速率限制:防止滥用
  5. IP白名单:生产环境可结合IP限制

应用场景选择

  • 内部工具:CORS + JWT
  • 公开但需保护API:CORS + 动态令牌 + 速率限制
  • 高安全性需求:客户端证书 + 请求签名

注意事项

  1. 没有任何前端方案能完全防止API滥用,关键操作应有后端二次验证
  2. 敏感操作应使用一次性令牌或二次确认
  3. 定期轮换密钥和证书
  4. 监控异常API调用模式

通过组合这些技术,可以有效限制只有你的SPA能够合法调用公共REST API,同时保持较好的用户体验和安全性平衡。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

没有搜到相关的文章

领券