61 lines
1.7 KiB
Go
61 lines
1.7 KiB
Go
// Package integration 提供给受信任第三方脚本的 JSON 接口。
|
|||
|
|
// 它与网页登录和 /api/v1/client 完全隔离,不能复用 Cookie 或 X-Client-Id。
|
||
|
|
package integration
|
||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/subtle"
|
||
|
|
"net/http"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"github.com/gin-gonic/gin"
|
||
|
|
|
||
|
|
"cmautobuy/admin/config"
|
||
|
|
)
|
||
|
|
|
||
|
|
const sourceContextKey = "catalog_integration_source"
|
||
|
|
|
||
|
|
// RequireCatalogToken 校验商品目录接口的专用 Bearer Token。
|
||
|
|
func RequireCatalogToken(cfg config.CatalogIntegrationConfig) gin.HandlerFunc {
|
||
|
|
return func(c *gin.Context) {
|
||
|
|
if !cfg.Enabled() {
|
||
|
|
integrationError(c, http.StatusServiceUnavailable, "INTEGRATION_DISABLED",
|
||
|
|
"商品目录接口尚未配置", true, nil)
|
||
|
|
c.Abort()
|
||
|
|
return
|
||
|
|
}
|
||
|
|
provided, ok := bearerToken(c.GetHeader("Authorization"))
|
||
|
|
if !ok || subtle.ConstantTimeCompare([]byte(provided), []byte(cfg.Token)) != 1 {
|
||
|
|
integrationError(c, http.StatusUnauthorized, "UNAUTHORIZED",
|
||
|
|
"接口凭据无效", false, nil)
|
||
|
|
c.Abort()
|
||
|
|
return
|
||
|
|
}
|
||
|
|
c.Set(sourceContextKey, cfg.Source)
|
||
|
|
c.Next()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func bearerToken(header string) (string, bool) {
|
||
|
|
parts := strings.Fields(header)
|
||
|
|
if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") || parts[1] == "" {
|
||
|
|
return "", false
|
||
|
|
}
|
||
|
|
return parts[1], true
|
||
|
|
}
|
||
|
|
|
||
|
|
func integrationSource(c *gin.Context) string {
|
||
|
|
value, _ := c.Get(sourceContextKey)
|
||
|
|
source, _ := value.(string)
|
||
|
|
return source
|
||
|
|
}
|
||
|
|
|
||
|
|
func integrationError(c *gin.Context, status int, code, message string, retryable bool, details any) {
|
||
|
|
if details == nil {
|
||
|
|
details = gin.H{}
|
||
|
|
}
|
||
|
|
c.JSON(status, gin.H{"error": gin.H{
|
||
|
|
"code": code, "message": message, "retryable": retryable,
|
||
|
|
"request_id": c.GetHeader("X-Request-Id"), "details": details,
|
||
|
|
}})
|
||
|
|
}
|