Go|Gin跨域问题

跨域问题

什么是跨域问题

在前后端分离的开发方式中,前端会提供一个URL(统一资源定位符)供用户访问,前端运行中会调用后台api接口的URL进行数据操作,这两个URL都包含以下部分:

  1. **通信协议:**常见的有http、tcp/ip
  2. 主机号(host):localhost(127.0.0.1),或者其他的ip地址
  3. 端口号: 例如常用的8080
  4. 资源路径: 端口号的内容

当页面发送一个新的请求,该请求中的URL与原页面的URL中的通信协议、主机号、端口号中任意一个有不同,就称为跨域访问。

举个例子,比如当前前端运行的页面的URLhttp://localhost:8080,在请求gin开发的后端时,该服务监听端口是http://localhost:8090或者http://GinProject:8080时,由于端口或者主机号不同,便发生了跨域访问。

如何判断跨域安全

在发生跨域的时候,浏览器和服务器会进行几个操作:

  1. 会向服务器发送一个OPTIONS类型的请求,即测试类型,又称为OPTIONS嗅探,同时会在Header中带上一个origin,后端跨域通过判断origin来判断是否同意跨域请求。
  2. 服务器中有相应Access-Control-Allow-Origin的值,通过与浏览器的origin值进行匹配,如果匹配成功则代表有跨域权限,允许跨域。
  3. 跨域请求通过,进行http请求

origin部分跨域请求处理,

func Cors()gin.HandlerFunc{
    return func(c *gin.Context){
        origin := c.Request.Header.Get("origin")	//origin值获取
        if origin != ""{
            //动态设置origin匹配,即同意所有跨域
            c.Header("Access-Controk-Allow-Origin",origin)
            //也是允许访问所有域,不过设置为'*'的时候不允许XMLHttpRequest携带Cookie
            c.Header("Access-Controk-Allow-Origin","*")
            //允许部分域,''中填写域名
            c.Header("Access-Controk-Allow-Origin",'')
        }
    }
}

CORS请求配置

在非简单请求,即PUT/DELETE以及字段类型Content-Typeapplication/json的请求中,会发送一个预检请求,即OPTIONS嗅探请求,也就是后端的CORS请求。

我们需要配置以下设置,来判断是否允许跨域请求

1.可访问域名

c.Header("Acces-Control-Allow-Origin",'*')
//必须字段。
//他的值是'*'或者origin的动态值,表示允许访问所有域
//或者设置的固定域名,表示访问对应域

2.可访问方法

c.Header("Access-Control-Allow-Methods",'PUT,DELETE,GET,POST')
//必须字段。
//值为用逗号分隔的字符串,该字符串中包含多个请求方法。
//其中的请求是所支持的请求,并且不能设置为动态的当前请求方法,因为会造成多次预检请求

3.支持的头信息字段

c.Header("Access-Control-Allow-Headers",'Content-Type, Content-Length, Token')
//如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。
//表示服务器支持的所有头信息字段

4.可被返回前端得到的字段

c.Header("Access-Control-Expose-Headers",'Access-Control-Allow-Headers, Token')
//可选字段
//表示XMLHttpRequest对象可获取的额外字段(不包含Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma)

5.是否可发送Cookie

c.Header("Access-Control-Allow-Credentials",'true')
//可选字段,如果不设置为true则不需要设置
//表示是否可以发送Cookie

6.预检有效期

c.Header("Access-Control-Max-Age","172800")
//可选字段
//表示该次OPTIONS请求有效期限,在此期间不要在此发送新的OPTIONS

Gin实现示例

中间件内容

package Mid

import (
	"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")
		if origin != "" {
			c.Header("Access-Control-Allow-Origin", origin)
			c.Header("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS")
			c.Header("Access-Control-Allow-Headers", "Content-Type, Content-Length, Token")
			c.Header("Access-Control-Expose-Headers", "Access-Control-Allow-Headers, Token")
			c.Header("Access-Control-Max-Age", "172800")
			c.Header("Access-Control-Allow-Credentials", "true")
			c.Set("content-type", "application/json")  设置返回格式是json
		}
		if method == "OPTIONS" {
			//c.JSON(200, Controller.R(200, nil, "Options Request"))
			c.AbortWithStatus(http.StatusNoContent)
		}
		c.Next()
	}
}

使用

var r *gin.Engine

func init()*gin.Engine{
    r = gin.Default()
    
    r.Use(Mid.Cors())
    
    r.POST("/")
    
    return r
}

参考文章:
https://juejin.cn/post/6987205879653204004
https://juejin.cn/post/7013611832543805454

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值