带cookie跨域问题的思路以及echo的解决方案
问题起因
前后端分离,前端要访问后端资源,而且需要携带cookie信息,这时碰到了跨域问题。一开始以为设置为允许跨域allow_origins为即可。可是浏览器还是拦截的请求,于是查看跨域规则,原来跨域allow_origins为时,只允许简单的跨域,比如get,post,但是如果携带cookie,则会出现失败。
思路
后来查看文档,原来按照跨域请求的规则,当跨域和来源一致时才可以携带cookie。详情见阮一峰的博客
echo框架中的解决办法
有了思路就好办了,echo框架中的跨域设置不够详细,做不到设置来源跨域。于是我修改了一下其中的跨域中间件,增加了一子域名的跨域。
实际上可以修改为,任意来源的跨域,但是这样就不能保证安全了,不过如果是做接口平台倒是可以这么办。
完整代码为:
package echo_cors
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
AllowAllHost bool
}
)
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
}
}
if config.AllowAllHost {
allowOrigin = c.Scheme()+"://"+req.Host
}
// 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)
}
}
}
用法
已经放到github了
这里增加了三个变量,AllowSubDomain,允许二级域名,MainDomain根域名,AllowAllHost 允许所有的跨域
- CORSWithConfig(CORSConfig{AllowCredentials:true,AllowSubDomain:true,MainDomain:"main.com"}) 允许子域名跨域
- CORSWithConfig(CORSConfig{AllowCredentials:true,AllowAllHost:true})
对于js,也要做对应修改,axios的修改如下:
const Axios = axios.create({
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
withCredentials: true
});
Axios.interceptors.request.use(
config => {
if (config.method === 'post' || config.method === 'put') {
if (config.data) {
var queryString = Object.keys(config.data)
.map(key => {
return encodeURIComponent(key) + '=' + encodeURIComponent(config.data[key]);
})
.join('&');
config.data = queryString;
}
return config;
}
return config;
},
error => {
return Promise.reject(error);
}
);
带cookie跨域问题的思路以及echo的解决方案的更多相关文章
- 基于Cookie跨域的单点登录问题
由于项目中,需要用的单点登录,主要的思路是:系统1:用户名密码-->写入Cookie-->其他系统读取Cookie. 1.在同一个服务器下的Cookie共享 @Component(&quo ...
- 解决cookie跨域访问
一.前言 随着项目模块越来越多,很多模块现在都是独立部署.模块之间的交流有时可能会通过cookie来完成.比如说门户和应用,分别部署在不同的机器或者web容器中,假如用户登陆之后会在浏览器客户端写入c ...
- cookie 跨域访问的解决方案
Cookie 同域单点登录 最近在做一个单点登录的系统整合项目,之前我们使用控件实现单点登录(以后可以介绍一下).但现在为了满足客户需求,在不使用控件情况下实现单点登录,先来介绍一下单点登录. ...
- asp.net关于Cookie跨域(域名)的问题
Cookie是一个伟大的发明,它允许Web开发者保留他们的用户的登录状态.但是当你的站点有一个以上的域名时就会出现问题了.在Cookie规范上 说,一个cookie只能用于一个域名,不能够发给其它的域 ...
- golang-在gin中cookie跨域设置(配合ajax)
1.当我在golang中,在前后端分离的情况下使用cookies时发现,跨域没有被允许.代码如下: func AccessJsMiddleware() gin.HandlerFunc { return ...
- nginx处理cookie跨域
今天在部署公司项目的时候碰到一个问题 项目地址是xxx.xx.xx.122:7480 项目A后台请求地址为xxx.xx.xx.123:8080/data-sso 开始nginx配置是 server { ...
- 解决前后端分离后的Cookie跨域问题
一. 前端Ajax关键配置 $.ajax({ type: "post", url: xxx, data: xxx, contentType: 'application/json', ...
- cookie 跨域解决方法
1.Nginx 正向和反向代理的区别 正向代理和反向代理的区别:正向代理隐藏真实客户端,反向代理隐藏真实服务端,图示: 2.cookie跨域问题 因为cookie存在跨域问题,其中一个解决方法是,设置 ...
- Iframe和Frame中实现cookie跨域的方法(转载)
在Iframe和Frame中默认是不支持Cookie跨域的,但通过设置P3P协议相关的响应头可以解决这一问题.关于p3p协议: P3P: Platform for Privacy Preference ...
随机推荐
- Alpha测试
1.测试计划 测试工作安排 成员名称 成员工作安排 林凯 注册登录页面相关功能测试 刘华强 主页面相关功能测试 吴文清 管理员页面相关功能测试 谢孟轩 用户页面相关功能测试 蔡振翼 回归测试 测试工具 ...
- Sphinx(coreseek)一些记录
之前用Sphinx(coreseek)几次,相对正常 这次用到,记录些问题 1.coreseek好像没人维护了吗,有点可惜. 2.centOS7 编译和coreseek版本有点问题,需要修改编译文件 ...
- 潭州课堂25班:Ph201805201 第七课:控制流程 (课堂笔记)
# 条件判断 s = '储蓄卡' if s == '男': # 如果if 表达式成立 ,则执行下级语句 print('男性') elif s == '女': # 如果上面表达式不成立,执行本次判断,本 ...
- 2016年3月9日Android实习日记
1. 解决 org.eclipse.swt.SWTException: Graphic is disposed 问题. 参考:http://www.xuebuyuan.com/1896964.html ...
- Python初识及变量
第一句python,输出 Hello world #!/usr/bin/evn python #指定解释器 #_*_ coding:utf- _*_ #指定编码 print("hello w ...
- PID控制器(比例-积分-微分控制器)- V
Linear Actuator - PID Control Introduction This application guide is designed to explain the basics ...
- java判断传进来的是否是图片
public static void main(String[] args) throws IOException { String filePath = "C:\\Users\\80975 ...
- GO开发环境搭建
GO开发环境搭建 1)下载GO SDK,并安装 https://golang.google.cn/dl/ 2)下载GO IDE:GOLAND,并安装 3)设置GOROOT和GOPATH 4)新建一个工 ...
- C#编程(八十三)---------- 程序集的含义
程序集的含义 一.程序集是包含一个或多个类型定义文件和资源文件的集合.它允许我们分析可重用类型的逻辑表示和物理表示. 相当于你定义了一个项目XXProject,项目存在很多文件(类,窗体,接口,资源等 ...
- 根据请求号(request ID)查找正在运行的sql
--下面的SQL可以根据Request ID找到对应的Session信息: select * from v$session where paddr in (select addr from v$pro ...