From 5852b2fdcf7d9eb0348a32c0c354c170d200df93 Mon Sep 17 00:00:00 2001 From: smail Date: Fri, 2 Oct 2026 07:42:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=A8=E6=96=B0=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E5=90=8E=E7=9A=84=E7=99=BB=E5=BD=95=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 允许带有初始化残留会话 Cookie 的同源登录请求通过通用 CSRF 检查,同时保留登录请求的来源、JSON 和同源校验,并补充回归用例。 --- backend/listen/http_server/https_server.go | 2 +- .../listen/http_server/https_server_test.go | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/backend/listen/http_server/https_server.go b/backend/listen/http_server/https_server.go index 4562a2d..b80e76a 100644 --- a/backend/listen/http_server/https_server.go +++ b/backend/listen/http_server/https_server.go @@ -320,7 +320,7 @@ func stateChangingMethod(method string) bool { func csrfExemptPath(path string) bool { switch normalizedAPIPath(path) { - case "/api/user/info": + case "/api/login", "/api/user/info": return true default: return false diff --git a/backend/listen/http_server/https_server_test.go b/backend/listen/http_server/https_server_test.go index 6c092ea..56998fc 100644 --- a/backend/listen/http_server/https_server_test.go +++ b/backend/listen/http_server/https_server_test.go @@ -39,6 +39,37 @@ func TestCSRFExemptsReadOnlyUserInfoEndpoint(t *testing.T) { } } +func TestLoginAllowsSameOriginRequestWithInitializationSessionCookie(t *testing.T) { + configureProductionOriginTest(t) + oldInit := config.IsInit + oldSession := session.Instance + defer func() { + config.SetInitState(oldInit) + session.Instance = oldSession + }() + config.SetInitState(true) + session.Instance = scs.New() + session.Instance.Cookie.Name = "smail_session" + + called := false + handler := session.Instance.LoadAndSave(contextIterceptor(controllers.HandlerFunc(func(ctx *context.Context, w http.ResponseWriter, r *http.Request) { + called = true + response.NewSuccessResponse("ok").FPrint(w) + }))) + + request := httptest.NewRequest(http.MethodPost, "https://mail.example.com/api/login", bytes.NewBufferString(`{"account":"test","password":"test"}`)) + request.Host = "mail.example.com" + request.Header.Set("Content-Type", "application/json") + request.Header.Set("Origin", "https://mail.example.com") + request.Header.Set("Sec-Fetch-Site", "same-origin") + request.AddCookie(&http.Cookie{Name: "smail_session", Value: "initialization-session"}) + recorder := httptest.NewRecorder() + handler.ServeHTTP(recorder, request) + + if !called { + t.Fatalf("same-origin login with an initialization session cookie was rejected: status=%d body=%s", recorder.Code, recorder.Body.String()) + } +} func configureProductionOriginTest(t *testing.T) { t.Helper() oldConfig := config.Instance