帶cookie跨域問題的思路以及echo的解決方案
阿新 • • 發佈:2018-07-20
urn ctu coo json 出現 stack white 思路 規則
完整代碼為:
問題起因
前後端分離,前端要訪問後端資源,而且需要攜帶cookie信息,這時碰到了跨域問題。一開始以為設置為允許跨域allow_origins為即可。可是瀏覽器還是攔截的請求,於是查看跨域規則,原來跨域allow_origins為時,只允許簡單的跨域,比如get,post,但是如果攜帶cookie,則會出現失敗。
思路
後來查看文檔,原來按照跨域請求的規則,當跨域和來源一致時才可以攜帶cookie。
echo框架中的解決辦法
有了思路就好辦了,echo框架中的跨域設置不夠詳細,做不到設置來源跨域。於是我修改了一下其中的跨域中間件,增加了一子域名的跨域。
實際上可以修改為,任意來源的跨域,但是這樣就不能保證安全了,不過如果是做接口平臺倒是可以這麽辦。
package middleware import ( "net/http" "strconv" "strings" "github.com/labstack/echo" "github.com/labstack/echo/middleware" ) type ( // CORSConfig defines the config for CORS middleware. CORSConfig struct { // Skipper defines a function to skip middleware. Skipper middleware.Skipper // AllowOrigin defines a list of origins that may access the resource. // Optional. Default value []string{"*"}. AllowOrigins []string `json:"allow_origins"` // AllowMethods defines a list methods allowed when accessing the resource. // This is used in response to a preflight request. // Optional. Default value DefaultCORSConfig.AllowMethods. AllowMethods []string `json:"allow_methods"` // AllowHeaders defines a list of request headers that can be used when // making the actual request. This in response to a preflight request. // Optional. Default value []string{}. AllowHeaders []string `json:"allow_headers"` // AllowCredentials indicates whether or not the response to the request // can be exposed when the credentials flag is true. When used as part of // a response to a preflight request, this indicates whether or not the // actual request can be made using credentials. // Optional. Default value false. AllowCredentials bool `json:"allow_credentials"` // ExposeHeaders defines a whitelist headers that clients are allowed to // access. // Optional. Default value []string{}. ExposeHeaders []string `json:"expose_headers"` // MaxAge indicates how long (in seconds) the results of a preflight request // can be cached. // Optional. Default value 0. MaxAge int `json:"max_age"` AllowSubDomain bool MainDomain string } ) var ( // DefaultCORSConfig is the default CORS middleware config. DefaultCORSConfig = CORSConfig{ Skipper: middleware.DefaultSkipper, AllowOrigins: []string{"*"}, AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.PATCH, echo.POST, echo.DELETE}, } ) // CORS returns a Cross-Origin Resource Sharing (CORS) middleware. // See: https://developer.mozilla.org/en/docs/Web/HTTP/Access_control_CORS func CORS() echo.MiddlewareFunc { return CORSWithConfig(DefaultCORSConfig) } // CORSWithConfig returns a CORS middleware with config. // See: `CORS()`. func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc { // Defaults if config.Skipper == nil { config.Skipper = DefaultCORSConfig.Skipper } if len(config.AllowOrigins) == 0 { config.AllowOrigins = DefaultCORSConfig.AllowOrigins } if len(config.AllowMethods) == 0 { config.AllowMethods = DefaultCORSConfig.AllowMethods } allowMethods := strings.Join(config.AllowMethods, ",") allowHeaders := strings.Join(config.AllowHeaders, ",") exposeHeaders := strings.Join(config.ExposeHeaders, ",") maxAge := strconv.Itoa(config.MaxAge) return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { if config.Skipper(c) { return next(c) } req := c.Request() res := c.Response() origin := req.Header.Get(echo.HeaderOrigin) allowOrigin := "" // Check allowed origins for _, o := range config.AllowOrigins { if o == "*" || o == origin { allowOrigin = o break } } if config.AllowSubDomain && config.MainDomain != ""{ if strings.Contains(origin,config.MainDomain) { allowOrigin = origin } } // Simple request if req.Method != echo.OPTIONS { res.Header().Add(echo.HeaderVary, echo.HeaderOrigin) res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin) if config.AllowCredentials { res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true") } if exposeHeaders != "" { res.Header().Set(echo.HeaderAccessControlExposeHeaders, exposeHeaders) } return next(c) } // Preflight request res.Header().Add(echo.HeaderVary, echo.HeaderOrigin) res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestMethod) res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestHeaders) res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin) res.Header().Set(echo.HeaderAccessControlAllowMethods, allowMethods) if config.AllowCredentials { res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true") } if allowHeaders != "" { res.Header().Set(echo.HeaderAccessControlAllowHeaders, allowHeaders) } else { h := req.Header.Get(echo.HeaderAccessControlRequestHeaders) if h != "" { res.Header().Set(echo.HeaderAccessControlAllowHeaders, h) } } if config.MaxAge > 0 { res.Header().Set(echo.HeaderAccessControlMaxAge, maxAge) } return c.NoContent(http.StatusNoContent) } } }
用法
這裏增加了兩個變量,AllowSubDomain,允許二級域名,MainDomain根域名
CORSWithConfig(CORSConfig{AllowCredentials:true,AllowSubDomain:true,MainDomain:"main.com"})
帶cookie跨域問題的思路以及echo的解決方案