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

如何在JavaScript中调用GCP私有WebSocket时传递Bearer认证头

解决浏览器端访问GCP Cloud Run私有WebSocket服务时传递Authorization Token的问题

问题根源

浏览器原生WebSocket API 不支持自定义Authorization这类非标准请求头,这是浏览器的安全限制。你尝试的1.3写法里的headers参数并非标准API的一部分,仅在Node.js等非浏览器环境的WebSocket库(如ws)中有效,所以浏览器里完全不生效。而Postman能成功,是因为它不受浏览器的同源策略和头字段限制。

可行解决方案

方案1:通过查询参数传递Token(需服务端配合)

如果你的Cloud Run服务端支持从URL查询参数中解析Token,可以直接把Token拼在URL后面:

const websocketUrl = 'wss://web-adaptor-service-lz7ymxgtha-ue.a.run.app';
const gcp_auth_token = 'eyJhbGciOiJSU**************************';

// 用access_token参数传递,需服务端验证该参数
const socket = new WebSocket(`${websocketUrl}?access_token=${gcp_auth_token}`);

注意:这种方式Token会暴露在URL中(可能出现在日志、历史记录里),如果对安全性要求极高,不推荐。

方案2:用Fetch提前完成握手(现代浏览器支持)

利用fetch自定义请求头完成WebSocket握手,再通过WebSocket.from()方法接管已建立的连接(Chrome 106+、Firefox 118+支持):

const websocketUrl = 'wss://web-adaptor-service-lz7ymxgtha-ue.a.run.app';
const gcp_auth_token = 'eyJhbGciOiJSU**************************';

async function connectWs() {
  try {
    // 发送WebSocket握手请求,自定义Authorization头
    const handshakeRes = await fetch(websocketUrl.replace('wss://', 'https://'), {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${gcp_auth_token}`,
        'Upgrade': 'websocket',
        'Connection': 'Upgrade',
        'Sec-WebSocket-Key': btoa(Math.random().toString()).slice(0, 16),
        'Sec-WebSocket-Version': '13'
      }
    });

    // 基于握手响应创建WebSocket连接
    const socket = WebSocket.from(handshakeRes);

    // 绑定事件监听
    socket.onopen = () => console.log('WebSocket连接成功');
    socket.onmessage = (e) => console.log('收到消息:', e.data);
    socket.onerror = (err) => console.error('连接错误:', err);
    socket.onclose = () => console.log('连接关闭');

    return socket;
  } catch (err) {
    console.error('握手失败:', err);
  }
}

// 调用连接函数
connectWs();

方案3:搭建Node.js代理服务器(兼容所有浏览器)

如果需要兼容旧浏览器,可在自己的服务器上做一层代理,前端连接代理,代理请求Cloud Run时自动添加Authorization头:

// 代理服务器代码(Node.js)
const express = require('express');
const http = require('http');
const { WebSocketServer } = require('ws');
const httpProxy = require('http-proxy');

const app = express();
const server = http.createServer(app);
const proxy = httpProxy.createProxyServer();

const CLOUD_RUN_WS_URL = 'wss://web-adaptor-service-lz7ymxgtha-ue.a.run.app';
const GCP_AUTH_TOKEN = 'eyJhbGciOiJSU**************************';

// 处理WebSocket升级请求
server.on('upgrade', (req, socket, head) => {
  // 给代理请求添加Authorization头
  req.headers.authorization = `Bearer ${GCP_AUTH_TOKEN}`;
  
  proxy.ws(req, socket, head, {
    target: CLOUD_RUN_WS_URL,
    changeOrigin: true
  });
});

// 启动代理服务器
const PORT = 3000;
server.listen(PORT, () => {
  console.log(`代理服务器运行在 http://localhost:${PORT}`);
});

前端直接连接代理服务器即可:

const socket = new WebSocket('ws://localhost:3000');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 23:50:32