问题起因

前后端分离,前端要访问后端资源,而且需要携带cookie信息,这时碰到了跨域问题。一开始以为设置为允许跨域allow_origins为即可。可是浏览器还是拦截的请求,于是查看跨域规则,原来跨域allow_origins为时,只允许简单的跨域,比如get,post,但是如果携带cookie,则会出现失败。

思路

后来查看文档,原来按照跨域请求的规则,当跨域和来源一致时才可以携带cookie。详情见阮一峰的博客

echo框架中的解决办法

有了思路就好办了,echo框架中的跨域设置不够详细,做不到设置来源跨域。于是我修改了一下其中的跨域中间件,增加了一子域名的跨域。

实际上可以修改为,任意来源的跨域,但是这样就不能保证安全了,不过如果是做接口平台倒是可以这么办。

完整代码为:

  1. package echo_cors
  2. import (
  3. "net/http"
  4. "strconv"
  5. "strings"
  6. "github.com/labstack/echo"
  7. "github.com/labstack/echo/middleware"
  8. )
  9. type (
  10. // CORSConfig defines the config for CORS middleware.
  11. CORSConfig struct {
  12. // Skipper defines a function to skip middleware.
  13. Skipper middleware.Skipper
  14. // AllowOrigin defines a list of origins that may access the resource.
  15. // Optional. Default value []string{"*"}.
  16. AllowOrigins []string `json:"allow_origins"`
  17. // AllowMethods defines a list methods allowed when accessing the resource.
  18. // This is used in response to a preflight request.
  19. // Optional. Default value DefaultCORSConfig.AllowMethods.
  20. AllowMethods []string `json:"allow_methods"`
  21. // AllowHeaders defines a list of request headers that can be used when
  22. // making the actual request. This in response to a preflight request.
  23. // Optional. Default value []string{}.
  24. AllowHeaders []string `json:"allow_headers"`
  25. // AllowCredentials indicates whether or not the response to the request
  26. // can be exposed when the credentials flag is true. When used as part of
  27. // a response to a preflight request, this indicates whether or not the
  28. // actual request can be made using credentials.
  29. // Optional. Default value false.
  30. AllowCredentials bool `json:"allow_credentials"`
  31. // ExposeHeaders defines a whitelist headers that clients are allowed to
  32. // access.
  33. // Optional. Default value []string{}.
  34. ExposeHeaders []string `json:"expose_headers"`
  35. // MaxAge indicates how long (in seconds) the results of a preflight request
  36. // can be cached.
  37. // Optional. Default value 0.
  38. MaxAge int `json:"max_age"`
  39. AllowSubDomain bool
  40. MainDomain string
  41. AllowAllHost bool
  42. }
  43. )
  44. var (
  45. // DefaultCORSConfig is the default CORS middleware config.
  46. DefaultCORSConfig = CORSConfig{
  47. Skipper: middleware.DefaultSkipper,
  48. AllowOrigins: []string{"*"},
  49. AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.PATCH, echo.POST, echo.DELETE},
  50. }
  51. )
  52. // CORS returns a Cross-Origin Resource Sharing (CORS) middleware.
  53. // See: https://developer.mozilla.org/en/docs/Web/HTTP/Access_control_CORS
  54. func CORS() echo.MiddlewareFunc {
  55. return CORSWithConfig(DefaultCORSConfig)
  56. }
  57. // CORSWithConfig returns a CORS middleware with config.
  58. // See: `CORS()`.
  59. func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
  60. // Defaults
  61. if config.Skipper == nil {
  62. config.Skipper = DefaultCORSConfig.Skipper
  63. }
  64. if len(config.AllowOrigins) == 0 {
  65. config.AllowOrigins = DefaultCORSConfig.AllowOrigins
  66. }
  67. if len(config.AllowMethods) == 0 {
  68. config.AllowMethods = DefaultCORSConfig.AllowMethods
  69. }
  70. allowMethods := strings.Join(config.AllowMethods, ",")
  71. allowHeaders := strings.Join(config.AllowHeaders, ",")
  72. exposeHeaders := strings.Join(config.ExposeHeaders, ",")
  73. maxAge := strconv.Itoa(config.MaxAge)
  74. return func(next echo.HandlerFunc) echo.HandlerFunc {
  75. return func(c echo.Context) error {
  76. if config.Skipper(c) {
  77. return next(c)
  78. }
  79. req := c.Request()
  80. res := c.Response()
  81. origin := req.Header.Get(echo.HeaderOrigin)
  82. allowOrigin := ""
  83. // Check allowed origins
  84. for _, o := range config.AllowOrigins {
  85. if o == "*" || o == origin {
  86. allowOrigin = o
  87. break
  88. }
  89. }
  90. if config.AllowSubDomain && config.MainDomain != "" {
  91. if strings.Contains(origin, config.MainDomain) {
  92. allowOrigin = origin
  93. }
  94. }
  95. if config.AllowAllHost {
  96. allowOrigin = c.Scheme()+"://"+req.Host
  97. }
  98. // Simple request
  99. if req.Method != echo.OPTIONS {
  100. res.Header().Add(echo.HeaderVary, echo.HeaderOrigin)
  101. res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin)
  102. if config.AllowCredentials {
  103. res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true")
  104. }
  105. if exposeHeaders != "" {
  106. res.Header().Set(echo.HeaderAccessControlExposeHeaders, exposeHeaders)
  107. }
  108. return next(c)
  109. }
  110. // Preflight request
  111. res.Header().Add(echo.HeaderVary, echo.HeaderOrigin)
  112. res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestMethod)
  113. res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestHeaders)
  114. res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin)
  115. res.Header().Set(echo.HeaderAccessControlAllowMethods, allowMethods)
  116. if config.AllowCredentials {
  117. res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true")
  118. }
  119. if allowHeaders != "" {
  120. res.Header().Set(echo.HeaderAccessControlAllowHeaders, allowHeaders)
  121. } else {
  122. h := req.Header.Get(echo.HeaderAccessControlRequestHeaders)
  123. if h != "" {
  124. res.Header().Set(echo.HeaderAccessControlAllowHeaders, h)
  125. }
  126. }
  127. if config.MaxAge > 0 {
  128. res.Header().Set(echo.HeaderAccessControlMaxAge, maxAge)
  129. }
  130. return c.NoContent(http.StatusNoContent)
  131. }
  132. }
  133. }

用法

已经放到github

这里增加了三个变量,AllowSubDomain,允许二级域名,MainDomain根域名,AllowAllHost 允许所有的跨域

  • CORSWithConfig(CORSConfig{AllowCredentials:true,AllowSubDomain:true,MainDomain:"main.com"}) 允许子域名跨域
  • CORSWithConfig(CORSConfig{AllowCredentials:true,AllowAllHost:true})

    对于js,也要做对应修改,axios的修改如下:
  1. const Axios = axios.create({
  2. headers: {
  3. 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
  4. },
  5. withCredentials: true
  6. });
  7. Axios.interceptors.request.use(
  8. config => {
  9. if (config.method === 'post' || config.method === 'put') {
  10. if (config.data) {
  11. var queryString = Object.keys(config.data)
  12. .map(key => {
  13. return encodeURIComponent(key) + '=' + encodeURIComponent(config.data[key]);
  14. })
  15. .join('&');
  16. config.data = queryString;
  17. }
  18. return config;
  19. }
  20. return config;
  21. },
  22. error => {
  23. return Promise.reject(error);
  24. }
  25. );

带cookie跨域问题的思路以及echo的解决方案的更多相关文章

  1. 基于Cookie跨域的单点登录问题

    由于项目中,需要用的单点登录,主要的思路是:系统1:用户名密码-->写入Cookie-->其他系统读取Cookie. 1.在同一个服务器下的Cookie共享 @Component(&quo ...

  2. 解决cookie跨域访问

    一.前言 随着项目模块越来越多,很多模块现在都是独立部署.模块之间的交流有时可能会通过cookie来完成.比如说门户和应用,分别部署在不同的机器或者web容器中,假如用户登陆之后会在浏览器客户端写入c ...

  3. cookie 跨域访问的解决方案

    Cookie 同域单点登录  最近在做一个单点登录的系统整合项目,之前我们使用控件实现单点登录(以后可以介绍一下).但现在为了满足客户需求,在不使用控件情况下实现单点登录,先来介绍一下单点登录.    ...

  4. asp.net关于Cookie跨域(域名)的问题

    Cookie是一个伟大的发明,它允许Web开发者保留他们的用户的登录状态.但是当你的站点有一个以上的域名时就会出现问题了.在Cookie规范上 说,一个cookie只能用于一个域名,不能够发给其它的域 ...

  5. golang-在gin中cookie跨域设置(配合ajax)

    1.当我在golang中,在前后端分离的情况下使用cookies时发现,跨域没有被允许.代码如下: func AccessJsMiddleware() gin.HandlerFunc { return ...

  6. nginx处理cookie跨域

    今天在部署公司项目的时候碰到一个问题 项目地址是xxx.xx.xx.122:7480 项目A后台请求地址为xxx.xx.xx.123:8080/data-sso 开始nginx配置是 server { ...

  7. 解决前后端分离后的Cookie跨域问题

    一. 前端Ajax关键配置 $.ajax({ type: "post", url: xxx, data: xxx, contentType: 'application/json', ...

  8. cookie 跨域解决方法

    1.Nginx 正向和反向代理的区别 正向代理和反向代理的区别:正向代理隐藏真实客户端,反向代理隐藏真实服务端,图示: 2.cookie跨域问题 因为cookie存在跨域问题,其中一个解决方法是,设置 ...

  9. Iframe和Frame中实现cookie跨域的方法(转载)

    在Iframe和Frame中默认是不支持Cookie跨域的,但通过设置P3P协议相关的响应头可以解决这一问题.关于p3p协议: P3P: Platform for Privacy Preference ...

随机推荐

  1. 从零搭建ES搜索服务(一)基本概念及环境搭建

    一.前言 本系列文章最终目标是为了快速搭建一个简易可用的搜索服务.方案并不一定是最优,但实现难度较低. 二.背景 近期公司在重构老系统,需求是要求知识库支持全文检索. 我们知道普通的数据库 like ...

  2. codeforces-1102e

    https://www.cnblogs.com/31415926535x/p/10439313.html 这道题很锻炼思维,,是到好题,,就是我不在状态,,没看出来线段间的关系,,学会了求一个区间里相 ...

  3. SQLite中SELECT基本形式

    SQLite中SELECT基本形式 每个数据库通常都包含多个表,而每个表又包含多条数据.要获取数据库中的数据,就需要SQL语言提供的查询语句SELECT.本章将讲解和SELECT语句相关的内容,其中包 ...

  4. 电商sku商品推荐

    1.逻辑回归LR进行实时离线三级品类训练. 2.通过用户对于实时.离线三级品类的偏好进行召回. 3.通过人的特征.sku特征.人sku交互特征.以及位置手机特征通过gbdt模型进行点击量预估.

  5. angular.js--------demo1

    <!doctype html><html ng-app> <head> <meta charset="utf-8"> </he ...

  6. Codeforces Round #109 (Div. 1) 题解 【ABC】

    A - Hometask 题意:给你一个字符串,然后再给你k个禁止挨在一起的字符串,问你最少删除多少个字符串,使得不会有禁忌的字符串对挨在一起.题目保证每个字符最多出现在一个禁忌中. 题解:由于每个字 ...

  7. Redis集群官方推荐方案 Redis-Cluster

    Redis-Cluster redis使用中遇到的瓶颈 我们日常在对于redis的使用中,经常会遇到一些问题 1.高可用问题,如何保证redis的持续高可用性. 2.容量问题,单实例redis内存无法 ...

  8. Mac下如何设置Eclipse默认浏览器为chrome

    http://stackoverflow.com/questions/5322574/how-can-i-set-chrome-as-default-external-browser-in-eclip ...

  9. Hyperledger超级账本在Centos7下搭建运行环境

    超级账本(hyperledger)是Linux基金会于2015年发起的推进区块链数字技术和交易验证的开源项目,加入成员包括:荷兰银行(ABN AMRO).埃森哲(Accenture)等十几个不同利益体 ...

  10. 奇怪吸引子---QiChen

    奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...