PHP作为WebSocket客户端不存在跨域问题,因其运行在服务端,不受浏览器同源策略限制;跨域校验仅发生在浏览器连接WebSocket服务端时,需服务端正确处理Origin校验与握手响应头。

PHP 本身不能直接作为 WebSocket 客户端去“连接”浏览器端的 WebSocket 服务并触发跨域问题——因为跨域限制是浏览器施加的,不是 PHP 的限制。真正需要处理跨域的,是 WebSocket 服务端(比如用 Swoole、Workerman 或 Node.js 写的 WS 服务)被浏览器访问时的 Origin 校验。
浏览器连 WebSocket 服务时提示 “Error in connection establishment: net::ERR_CONNECTION_REFUSED” 或 “Unexpected response code: 400”
这往往不是跨域报错,而是服务端没开、路径不对、或协议不匹配(ws:// vs wss://)。但如果你看到控制台明确提示 Blocked by CORS policy,说明服务端返回了非 101 状态码,或没正确响应 Sec-WebSocket-Accept,又或者在握手阶段拒绝了非法 Origin。
- 检查服务端是否显式校验了
$_SERVER['HTTP_ORIGIN']并做了exit或返回 403 - 确认握手响应头包含:
HTTP/1.1 101 Switching Protocols、Upgrade: websocket、Connection: Upgrade、Sec-WebSocket-Accept: xxx - 如果用了 Nginx 反向代理 WebSocket,必须透传
Upgrade和Connection头,否则握手失败
Swoole WebSocket Server 如何允许指定 Origin
Swoole 默认不校验 Origin,但很多开发者会手动加校验逻辑。如果你在 onHandshake 回调里写了判断,就得主动放行:
$server->on('handshake', function ($request, $response) {
$origin = $request->header['origin'] ?? '';
$allowedOrigins = ['https://example.com', 'http://localhost:3000'];
if (!in_array($origin, $allowedOrigins)) {
$response->end();
return false;
}
// 必须设置这些 header 才能完成握手
$response->header('Sec-WebSocket-Accept', base64_encode(sha1($request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true)));
$response->header('Upgrade', 'websocket');
$response->header('Connection', 'Upgrade');
$response->status(101);
$response->end();
});
- 漏掉
status(101)或任意一个必要 header,浏览器就会报 400 - 不要在
onHandshake里 echo 或 var_dump,会污染响应体 - 生产环境建议用白名单,而不是直接允许
*(WebSocket 协议不支持Access-Control-Allow-Origin: *在 101 响应中)
PHP 作为 WebSocket 客户端(如用 Ratchet 或 ReactPHP)根本不存在跨域问题
PHP 脚本运行在服务端,发起的是 TCP 连接,不受同源策略约束。你用 fsockopen、stream_socket_client 或 Ratchet\Client\connect() 连任意 ws:// 地址都不会触发跨域检查。
立即学习“PHP免费学习笔记(深入)”;
- 出错通常是 DNS 解析失败、防火墙拦截、TLS 版本不兼容(
wss://需要 OpenSSL 支持)、或服务端关闭了非浏览器连接 - 如果服务端依赖
Origin或User-Agent做识别,你得手动在 WebSocket 握手请求头里带上:Origin: https://yourdomain.com - Ratchet 客户端可通过
$connector->connect($url, [], $headers)传自定义 header
真正的坑在于混淆了「谁在发起连接」和「谁在执行策略」:浏览器连 WS 服务才受跨域约束;PHP 连 WS 服务只是普通 socket 通信。多数人卡住的地方,其实是服务端握手逻辑写错了,或者反向代理没配对 Upgrade 头。











