From d47c03c3d6ae45ed85457c0c257c956b95c7e1d3 Mon Sep 17 00:00:00 2001 From: wangzhengkun Date: Thu, 4 Aug 2022 17:21:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0cors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app.yaml | 15 +++++++++ backend/configs/config.go | 1 + backend/configs/cors.go | 14 +++++++++ backend/middlerware/cors.go | 63 +++++++++++++++++++++++++++++++++++++ backend/middlerware/jwt.go | 2 +- 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 backend/configs/cors.go create mode 100644 backend/middlerware/cors.go diff --git a/backend/app.yaml b/backend/app.yaml index 10acbbaac..56b5ecb54 100644 --- a/backend/app.yaml +++ b/backend/app.yaml @@ -30,3 +30,18 @@ log: log_size: 50 #日志文件大小,单位是 MB log_backup: 10 #最大过期日志保留个数 log_data: 7 #保留过期文件最大时间,单位 天 + +# 跨域配置 +cors: + mode: whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝 + whitelist: + - allow-origin: example1.com + allow-headers: content-type + allow-methods: GET, POST + expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type + allow-credentials: true # 布尔值 + - allow-origin: example2.com + allow-headers: content-type + allow-methods: GET, POST + expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type + allow-credentials: true # 布尔值 \ No newline at end of file diff --git a/backend/configs/config.go b/backend/configs/config.go index 8abf6ec0a..881b8d251 100644 --- a/backend/configs/config.go +++ b/backend/configs/config.go @@ -6,4 +6,5 @@ type ServerConfig struct { System System `mapstructure:"system"` LogConfig LogConfig `mapstructure:"log"` JWT JWT `mapstructure:"jwt"` + CORS CORS `mapstructure:"cors"` } diff --git a/backend/configs/cors.go b/backend/configs/cors.go new file mode 100644 index 000000000..1a2889f47 --- /dev/null +++ b/backend/configs/cors.go @@ -0,0 +1,14 @@ +package configs + +type CORS struct { + Mode string `mapstructure:"mode"` + WhiteList []CORSWhiteList `mapstructure:"whitelist"` +} + +type CORSWhiteList struct { + AllowOrigin string `mapstructure:"allow-origin"` + AllowMethods string `mapstructure:"allow-methods"` + AllowHeaders string `mapstructure:"allow-headers"` + ExposeHeaders string `mapstructure:"expose-headers"` + AllowCredentials bool `mapstructure:"allow-credentials"` +} diff --git a/backend/middlerware/cors.go b/backend/middlerware/cors.go new file mode 100644 index 000000000..22dbf376c --- /dev/null +++ b/backend/middlerware/cors.go @@ -0,0 +1,63 @@ +package middlerware + +import ( + "github.com/1Panel-dev/1Panel/configs" + "github.com/1Panel-dev/1Panel/global" + "github.com/gin-gonic/gin" + "net/http" +) + +func Cors() gin.HandlerFunc { + return func(c *gin.Context) { + method := c.Request.Method + origin := c.Request.Header.Get("Origin") + c.Header("Access-Control-Allow-Origin", origin) + c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id") + c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT") + c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type, New-Token, New-Expires-At") + c.Header("Access-Control-Allow-Credentials", "true") + + if method == "OPTIONS" { + c.AbortWithStatus(http.StatusNoContent) + } + c.Next() + } +} + +func CorsByRules() gin.HandlerFunc { + mode := global.Config.CORS.Mode + if mode == "allow-all" { + return Cors() + } + return func(c *gin.Context) { + whitelist := checkCors(c.GetHeader("origin")) + if whitelist != nil { + c.Header("Access-Control-Allow-Origin", whitelist.AllowOrigin) + c.Header("Access-Control-Allow-Headers", whitelist.AllowHeaders) + c.Header("Access-Control-Allow-Methods", whitelist.AllowMethods) + c.Header("Access-Control-Expose-Headers", whitelist.ExposeHeaders) + if whitelist.AllowCredentials { + c.Header("Access-Control-Allow-Credentials", "true") + } + } + if whitelist == nil && mode == "strict-whitelist" && !(c.Request.Method == "GET" && c.Request.URL.Path == "/health") { + c.AbortWithStatus(http.StatusForbidden) + } else { + if c.Request.Method == "OPTIONS" { + c.AbortWithStatus(http.StatusNoContent) + } + } + + c.Next() + } +} + +func checkCors(currentOrigin string) *configs.CORSWhiteList { + for _, whitelist := range global.Config.CORS.WhiteList { + // 遍历配置中的跨域头,寻找匹配项 + if currentOrigin == whitelist.AllowOrigin { + return &whitelist + } + } + return nil +} diff --git a/backend/middlerware/jwt.go b/backend/middlerware/jwt.go index a03155778..32e9940d2 100644 --- a/backend/middlerware/jwt.go +++ b/backend/middlerware/jwt.go @@ -11,7 +11,7 @@ import ( func JwtAuth() gin.HandlerFunc { return func(c *gin.Context) { - token := c.Request.Header.Get("x-token") + token := c.Request.Header.Get("Authorization") re := result.NewResult(c) if token == "" { re.Error(errres.JwtNotFound)