WebSocket 跨域问题解决方案:完整实战流程

问题本质

WebSocket 协议本身支持跨域,但浏览器会验证服务器响应头中的 Origin 字段。若服务端未正确配置,浏览器会拒绝连接。核心解决方案分两种:

  1. 服务端配置 CORS 头部
  2. Nginx 反向代理统一域名

方案一:服务端 CORS 配置(原生实现)

步骤 1:验证握手阶段

WebSocket 建立连接时,浏览器发送包含 Origin 的 HTTP 请求。服务端需在握手阶段返回允许的源:

// Node.js 示例 (使用 ws 库)
const WebSocket = require('ws');

const server = new WebSocket.Server({ port: 8080 });

server.on('connection', (socket, req) => {
  // 业务逻辑...
});

// 处理握手请求
server.on('headers', (headers, req) => {
  const origin = req.headers.origin;
  if (origin === 'https://your-frontend.com') {
    headers.push('Access-Control-Allow-Origin: https://your-frontend.com');
    headers.push('Access-Control-Allow-Credentials: true');
  }
});

关键响应头
头部字段 说明
Access-Control-Allow-Origin 允许的源(需精确匹配)
Access-Control-Allow-Credentials 是否允许携带 Cookie(需设为 true
步骤 2:客户端连接
// 浏览器端代码
const socket = new WebSocket('wss://your-backend.com');

socket.onopen = () => {
  console.log('跨域连接成功!');
};


方案二:Nginx 反向代理(生产推荐)

架构优势
客户端 → Nginx (统一域名) → WebSocket 服务
       ↑ 解决跨域            ↑ 隐藏真实端口

配置步骤
  1. 修改 Nginx 配置
server {
  listen 80;
  server_name your-domain.com;

  location /ws {
    proxy_pass http://localhost:8080; # 后端WS服务地址
    
    # 关键协议升级配置
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    # 跨域控制
    proxy_set_header Origin '';
    add_header Access-Control-Allow-Origin * always;
  }
}

  1. 重载 Nginx
sudo nginx -s reload

  1. 客户端连接
// 使用代理路径连接
const socket = new WebSocket('wss://your-domain.com/ws');


完整流程对比

方案 适用场景 优势 注意事项
CORS 配置 直接控制后端代码 无需额外组件 需处理 OPTIONS 预检请求
Nginx 代理 多服务/微服务架构 统一入口、负载均衡、隐藏端口 需维护 Nginx 配置

调试技巧

  1. 浏览器检查

    • 在 DevTools → Network 查看 WebSocket 请求的 Response Headers
    • 验证是否存在 101 Switching Protocols 状态码
  2. 常见错误

    • 403 Forbidden:Nginx 权限问题
    • 426 Upgrade Required:未配置协议升级头
    • Origin mismatch:CORS 源配置错误
  3. 测试工具

    # 使用 wscat 测试连接
    npm install -g wscat
    wscat -c wss://your-domain.com/ws
    


安全增强建议

  1. Origin 白名单校验

    # Nginx 中校验 Origin
    if ($http_origin ~* (https?://(allowed1.com|allowed2.com))) {
      add_header Access-Control-Allow-Origin $http_origin;
    }
    

  2. WSS 加密传输

    # 配置 SSL
    listen 443 ssl;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/privkey.pem;
    

  3. 连接限流

    # 限制每秒新连接数
    limit_conn_zone $binary_remote_addr zone=wslimit:10m;
    limit_conn wslimit 20;
    

通过以上方案,可彻底解决 WebSocket 跨域问题。生产环境推荐使用 Nginx 反向代理 + WSS 加密 组合方案,兼顾安全性与可维护性。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐