go websocket服务端默认拒绝非本地origin是因websocket.upgrader的checkorigin方法默认返回false所致;需显式配置checkorigin,开发可临时设为return true,生产必须用白名单校验origin,包括处理"null"情况。

Go WebSocket服务端默认拒绝非本地Origin
这个错误不是客户端问题,而是服务端 websocket.Upgrader 的 CheckOrigin 方法默认返回 false 导致的。只要请求头带了 Origin(几乎所有浏览器、fetch、XMLHttpRequest 都会带),且没显式放行,就会被 403 拒绝。
gorilla/websocket 中必须显式配置 CheckOrigin
用 github.com/gorilla/websocket 时,不能依赖默认行为。最简修复是允许所有来源(仅限开发):
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
但要注意:
-
return true是硬编码放行,上线前必须替换为白名单逻辑 - 如果用
net/http原生Upgrader(Go 1.22+),接口略有不同:func(r *http.Request) bool仍适用,但字段名是CheckOrigin不变 - 某些旧版包(如已归档的
code.google.com/p/go.net/websocket)不暴露该钩子,必须换库
生产环境应校验具体 Origin 而非全放行
直接写 return true 在生产中等于关闭安全边界。正确做法是比对白名单:
allowedOrigins := map[string]bool{
"https://myapp.com": true,
"https://staging.myapp.com": true,
}
upgrader.CheckOrigin = func(r *http.Request) bool {
origin := r.Header.Get("Origin")
return allowedOrigins[origin]
}
常见疏漏点:
- 忘记处理
Origin: null(本地file://页面或某些测试工具触发) - 没考虑协议、端口、路径是否严格匹配(比如
http://localhost:3000≠http://localhost) - 在反向代理后部署时,
Origin头可能被篡改或丢失,需检查 Nginx/Apache 是否透传了该头
前端发起连接时 Origin 可能意外为 null
如果你用双击打开 HTML 文件(file:// 协议),Chrome/Firefox 会设 Origin: null,此时即使服务端放行所有非空 Origin,也会失败。
验证方式:在浏览器控制台执行 new WebSocket("ws://localhost:8080"),看 Network 面板里请求头的 Origin 值。
解决办法只有两个:
- 前端改用本地服务器启动(如
python3 -m http.server或 VS Code Live Server) - 服务端逻辑显式接受
"null":return origin == "null" || allowedOrigins[origin]
别碰 --disable-web-security —— 它绕过整个浏览器沙箱,和调试无关,纯属自欺欺人。











