Smail/backend/utils/csrf/csrf_test.go
smail f60d3b0880
Some checks are pending
Security Checks / security (push) Waiting to run
整理前后端与测试构建目录并完善配置和安全引导
统一 frontend、backend、test、test-log 和 out 目录,更新构建、部署及测试入口;纳入配置管理兼容与首次安全引导修复;排除本机配置、密钥和测试产物。
2026-09-05 19:19:52 +08:00

79 lines
2.2 KiB
Go

package csrf
import (
"net/http"
"net/http/httptest"
"testing"
"git.pcux.cn/xuans/Smail/session"
"github.com/alexedwards/scs/v2"
)
func testRequestWithToken(t *testing.T, manager *scs.SessionManager, stored, header, cookie string) *http.Request {
t.Helper()
request := httptest.NewRequest(http.MethodPost, "https://mail.example.com/api/settings", nil)
loaded, err := manager.Load(request.Context(), "")
if err != nil {
t.Fatal(err)
}
request = request.WithContext(loaded)
if stored != "" {
manager.Put(request.Context(), SessionKey, stored)
}
if header != "" {
request.Header.Set(HeaderName, header)
}
if cookie != "" {
request.AddCookie(&http.Cookie{Name: CookieName, Value: cookie})
}
return request
}
func TestValidRejectsMissingAndMismatchedTokens(t *testing.T) {
old := session.Instance
manager := scs.New()
session.Instance = manager
t.Cleanup(func() { session.Instance = old })
cases := []struct {
name string
stored string
header string
cookie string
}{
{name: "missing-header", stored: "token", cookie: "token"},
{name: "missing-cookie", stored: "token", header: "token"},
{name: "header-mismatch", stored: "token", header: "other", cookie: "token"},
{name: "cookie-mismatch", stored: "token", header: "token", cookie: "other"},
{name: "missing-session", header: "token", cookie: "token"},
}
for _, item := range cases {
t.Run(item.name, func(t *testing.T) {
if Valid(testRequestWithToken(t, manager, item.stored, item.header, item.cookie)) {
t.Fatal("invalid CSRF token combination was accepted")
}
})
}
}
func TestClearInvalidatesExistingToken(t *testing.T) {
old := session.Instance
manager := scs.New()
session.Instance = manager
t.Cleanup(func() { session.Instance = old })
request := testRequestWithToken(t, manager, "token", "token", "token")
if !Valid(request) {
t.Fatal("valid CSRF token was rejected")
}
recorder := httptest.NewRecorder()
Clear(recorder, request, true)
if Valid(request) {
t.Fatal("cleared CSRF token remained valid")
}
cookies := recorder.Result().Cookies()
if len(cookies) != 1 || cookies[0].Name != CookieName || cookies[0].MaxAge >= 0 || !cookies[0].Secure {
t.Fatalf("unexpected CSRF clear cookie: %+v", cookies)
}
}