fix: authenticate same-origin player navigation (#54)

This commit is contained in:
ila
2026-08-13 21:32:49 +08:00
parent b8d14dbdae
commit abbc9a7093
+38
View File
@@ -48,6 +48,21 @@ func Require(permission string, next http.Handler) http.Handler {
})
}
// RequireSameOriginFrame authenticates browser iframe navigation that cannot
// attach the X-Product header used by API clients. Fetch Metadata keeps this
// narrow: only a same-origin iframe navigation with a valid Sense session is
// accepted.
func RequireSameOriginFrame(permission string, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
module := activeModule.Load()
if module == nil {
platform.WriteError(w, &platform.APIError{Status: http.StatusServiceUnavailable, Code: "identity_not_ready", Message: "身份服务尚未就绪"})
return
}
module.RequireSameOriginFrame(permission, next).ServeHTTP(w, r)
})
}
func PrincipalFromContext(ctx context.Context) (Principal, bool) {
principal, ok := ctx.Value(principalContextKey{}).(Principal)
return principal, ok
@@ -84,6 +99,28 @@ func (m *Module) Require(permission string, next http.Handler) http.Handler {
}))
}
func (m *Module) RequireSameOriginFrame(permission string, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Sec-Fetch-Site") != "same-origin" ||
r.Header.Get("Sec-Fetch-Mode") != "navigate" ||
r.Header.Get("Sec-Fetch-Dest") != "iframe" {
platform.WriteError(w, &platform.APIError{Status: http.StatusUnauthorized, Code: "unauthorized", Message: "登录状态无效"})
return
}
cookie, err := r.Cookie(sessionCookieName)
if err != nil {
platform.WriteError(w, &platform.APIError{Status: http.StatusUnauthorized, Code: "unauthorized", Message: "登录状态无效"})
return
}
principal, err := m.service.Authenticate(r.Context(), cookie.Value)
if err != nil || !HasPermission(principal.Role, permission) {
platform.WriteError(w, &platform.APIError{Status: http.StatusUnauthorized, Code: "unauthorized", Message: "登录状态无效"})
return
}
next.ServeHTTP(w, r.WithContext(context.WithValue(r.Context(), principalContextKey{}, principal)))
})
}
func (m *Module) bootstrap(w http.ResponseWriter, r *http.Request) {
var request struct {
Username string `json:"username"`
@@ -220,3 +257,4 @@ func SecureCookieFromEnvironment(value string, memoryMode bool) bool {
}
return !strings.EqualFold(value, "false")
}