fix(gateway): WebSocket 同源/loopback 等价放行,修复生产同源跨源 403
后端 go:embed 自服务前端时,页面 origin 与网关 Host 一致(production 模式), 但不在 dev 阶段 ALLOWED_ORIGINS(5173/3000)白名单内,originChecker 记 403 导致 WS /ws/chat 握手失败。 改为:同源(origin host == request host)及 loopback 别名(localhost<->127.0.0.1) 自动放行;跨源(不同主机名)仍走白名单。安全不降级:跨源非白名单依旧拒绝。 新增 TestOriginCheckerSameHost 覆盖同源/loopback等效/跨源拒绝/同主机异端口。
This commit is contained in:
1 parent
13c7c52860
commit
20305631c5
2 files changed
+93
-3
No files matched your search
@@ -876,6 +876,44 @@ func TestOriginChecker(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOriginCheckerSameHost(t *testing.T) {
|
||||
t.Parallel()
|
||||
allowed := map[string]bool{"http://ok.example": true}
|
||||
checker := originChecker(allowed, false)
|
||||
|
||||
// Same host (exact) — production mode serving embedded frontend on the gateway port.
|
||||
req := httptest.NewRequest(http.MethodGet, "/ws/chat", nil)
|
||||
req.Host = "localhost:10942"
|
||||
req.Header.Set("Origin", "http://localhost:10942")
|
||||
if !checker(req) {
|
||||
t.Fatal("same host origin should be allowed")
|
||||
}
|
||||
|
||||
// Loopback alias: host is 127.0.0.1 but client origin uses localhost.
|
||||
req2 := httptest.NewRequest(http.MethodGet, "/ws/chat", nil)
|
||||
req2.Host = "127.0.0.1:10942"
|
||||
req2.Header.Set("Origin", "http://localhost:10942")
|
||||
if !checker(req2) {
|
||||
t.Fatal("localhost<->127.0.0.1 loopback alias should be allowed")
|
||||
}
|
||||
|
||||
// Different host must still be rejected (not a same-origin, not whitelisted).
|
||||
req3 := httptest.NewRequest(http.MethodGet, "/ws/chat", nil)
|
||||
req3.Host = "evil.example:10942"
|
||||
req3.Header.Set("Origin", "http://localhost:10942")
|
||||
if checker(req3) {
|
||||
t.Fatal("cross-host origin should be rejected")
|
||||
}
|
||||
|
||||
// Same host, different port: still same-origin (same physical host), so allow.
|
||||
req4 := httptest.NewRequest(http.MethodGet, "/ws/chat", nil)
|
||||
req4.Host = "localhost:8080"
|
||||
req4.Header.Set("Origin", "http://localhost:10942")
|
||||
if !checker(req4) {
|
||||
t.Fatal("same host (different port) should be allowed — port is not a cross-origin boundary")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWSTokenExtraction(t *testing.T) {
|
||||
t.Parallel()
|
||||
if got := wsToken(reqWithQuery("token", "abc")); got != "abc" {
|
||||
|
||||
Reference in new issue
Block a user