package middleware import ( "net/http" "strings" "github.com/1Panel-dev/1Panel/core/app/dto" "github.com/1Panel-dev/1Panel/core/constant" "github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/i18n" "github.com/gin-gonic/gin" ) func CSRFTokenGuard() gin.HandlerFunc { return func(c *gin.Context) { if !requiresCSRFTokenCheck(c) { c.Next() return } token := strings.TrimSpace(c.GetHeader(constant.CSRFHeaderName)) if !global.SESSION.CheckCSRFToken(c, token) { c.AbortWithStatusJSON(http.StatusForbidden, dto.Response{ Code: http.StatusForbidden, Message: i18n.GetMsgWithMap("ErrNotLogin", map[string]interface{}{"detail": "CSRF token invalid"}), Data: nil, }) return } c.Next() } } func requiresCSRFTokenCheck(c *gin.Context) bool { if c.GetBool("LOCAL_REQUEST") { return false } unsafeMethod := c.Request.Method != http.MethodGet && c.Request.Method != http.MethodHead && c.Request.Method != http.MethodOptions && c.Request.Method != http.MethodTrace if !unsafeMethod { return false } if !strings.HasPrefix(c.Request.URL.Path, "/api/v2/") { return false } switch c.Request.URL.Path { case "/api/v2/core/auth/login", "/api/v2/core/auth/mfalogin", "/api/v2/core/auth/passkey/begin", "/api/v2/core/auth/passkey/finish", "/api/v2/core/auth/oidc/begin", "/api/v2/core/auth/oidc/finish": return false case "/api/v2/core/auth/saml2/begin", "/api/v2/core/auth/saml2/acs", "/api/v2/core/auth/saml2/finish", "/api/v2/core/auth/saml2/logout": return false } if c.GetBool("API_AUTH") { return false } sessionID, err := c.Cookie(constant.SessionName) return err == nil && sessionID != "" }