Files
compute-engine/middleware/auth_origin.go
T
Pine 28e53d90fc feat: 算力引擎 Go 后端核心(new-api)
- 统一 OpenAI 兼容 /v1 中继 + 渠道/额度/令牌/流水
- 各领域包:relay 模型网关、model 数据层、controller 管理 API
2026-08-23 22:38:46 +08:00

77 lines
2.1 KiB
Go

package middleware
import (
"crypto/subtle"
"net/http"
"net/url"
"strings"
"github.com/QuantumNous/new-api/common"
"github.com/gin-gonic/gin"
)
// SessionCookieOriginGuard protects cookie-authenticated refresh/logout
// endpoints when secure cookie mode is enabled. In insecure local development
// mode it preserves the legacy behavior and intentionally performs no Origin
// validation. It never adds CORS response headers and must not be installed on
// relay routes.
func SessionCookieOriginGuard() gin.HandlerFunc {
return func(c *gin.Context) {
if !common.SessionCookieSecure {
c.Next()
return
}
origin, ok := requestBrowserOrigin(c.Request)
if !ok || !isAllowedSessionOrigin(c.Request, origin) {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
"success": false,
"code": "AUTH_ORIGIN_FORBIDDEN",
"message": "request origin is not allowed",
})
return
}
c.Next()
}
}
func requestBrowserOrigin(request *http.Request) (string, bool) {
originValues := request.Header.Values("Origin")
if len(originValues) > 1 {
return "", false
}
if len(originValues) == 1 {
if strings.Contains(originValues[0], ",") {
return "", false
}
origin, err := common.NormalizeOrigin(originValues[0])
return origin, err == nil
}
refererValues := request.Header.Values("Referer")
if len(refererValues) != 1 {
return "", false
}
referer, err := url.Parse(strings.TrimSpace(refererValues[0]))
if err != nil || referer.Scheme == "" || referer.Host == "" || referer.User != nil {
return "", false
}
origin, err := common.NormalizeOrigin(referer.Scheme + "://" + referer.Host)
return origin, err == nil
}
func isAllowedSessionOrigin(request *http.Request, origin string) bool {
requestScheme := "http"
if request.TLS != nil {
requestScheme = "https"
}
requestOrigin, err := common.NormalizeOrigin(requestScheme + "://" + request.Host)
if err == nil && subtle.ConstantTimeCompare([]byte(origin), []byte(requestOrigin)) == 1 {
return true
}
for _, trustedOrigin := range common.SessionCookieTrustedURLs {
if subtle.ConstantTimeCompare([]byte(origin), []byte(trustedOrigin)) == 1 {
return true
}
}
return false
}