如何在go中实现处理跨域请求的中间件?

跨域请求

什么是域?

协议+域名+端口号都相同才是同域(同源策略),而同源策略又分两种

  • OM 同源策略:禁止对不同源页面 DOM 进行操作。这里主要场景是 iframe 跨域的情况,不同域名的 iframe 是限制互相访问的。
  • XMLHttpRequest 同源策略:禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。

CORS/跨资源共享

跨源资源共享 Cross-Origin Resource Sharing(CORS) 是一个新的 W3C 标准,它新增的一组HTTP首部字段,允许服务端其声明哪些源站有权限访问哪些资源。换言之,它允许浏览器向声明了 CORS 的跨域服务器,发出 XMLHttpReuest 请求,从而克服 Ajax 只能同源使用的限制。

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

简单请求

  • 请求方法为 HEAD、GET、POST中的一种。
  • HTTP头信息不超过一下几种:
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)

对于简单请求,浏览器会自动在请求的头部添加一个 Origin 字段来说明本次请求来自哪个源(协议 + 域名 + 端口),服务端则通过这个值判断是否接收本次请求。如果 Origin 在许可范围内,则服务器返回的响应会多出几个头信息

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, Content-Length
Access-Control-Allow-Origin: *
Content-Type: text/html; charset=utf-8

非简单请求

对服务器有特殊要求的请求,比如请求方法是 PUT 或 DELETE ,或者 Content-Type 字段的类型是 application/json。

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight),预检请求其实就是我们常说的 OPTIONS 请求,表示这个请求是用来询问的。具体如下:

  1. 会首先发送一个OPTIONS类型的请求,该请求是测试类型的,又称之为options嗅探,同时会在header中带上origin,判断是否有跨域请求权限,
  2. 然后服务器相应Access-Control-Allow-Origin的值,该值会与浏览器的origin值进行匹配,如果能够匹配通过,则表示有跨域访问的权限。
  3. 跨域访问权限检查通过,会正式发送POST请求。

头信息里面,关键字段 Origin ,表示请求来自哪个源,除 Origin 字段,"预检"请求的头信息包括两个特殊字段:

  • Access-Control-Request-Method

    用来列出浏览器的CORS请求会用到哪些HTTP方法(必需)

  • Access-Control-Request-Headers

    该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段

通过配置这些参数来处理跨域请求

func Cors(context *gin.Context) {
	method := context.Request.Method
	// 必须,接受指定域的请求,可以使用*不加以限制,但不安全
	//context.Header("Access-Control-Allow-Origin", "*")
	context.Header("Access-Control-Allow-Origin", context.GetHeader("Origin"))
	fmt.Println(context.GetHeader("Origin"))
	// 必须,设置服务器支持的所有跨域请求的方法
	context.Header("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS")
	// 服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段
	context.Header("Access-Control-Allow-Headers", "Content-Type, Content-Length, Token")
	// 可选,设置XMLHttpRequest的响应对象能拿到的额外字段
	context.Header("Access-Control-Expose-Headers", "Access-Control-Allow-Headers, Token")
	// 可选,是否允许后续请求携带认证信息Cookir,该值只能是true,不需要则不设置
	context.Header("Access-Control-Allow-Credentials", "true")
	// 放行所有OPTIONS方法
	if method == "OPTIONS" {
		context.AbortWithStatus(http.StatusNoContent)
		return
	}
	context.Next()
}

* 常常使用在公开的无敏感信息的接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值