vue axios http网络请求头包含非 CORS 白名单的请求标头 也被称作“简单标头”时, post, put,path,delete等请求CORS问题总结与解决方法

15 篇文章 0 订阅
3 篇文章 0 订阅

何谓http 非“简单标头”? 

在我们从前端发送网络请求时所携带的标头非这些标头“Accept, Accept-Language, Content-Language, Content-Type, Range” 时即“非简单标头”。 

预检请求

当我们发送的请求头包含的请求头不是CORS 白名单的请求标头 时浏览器就会在请求发起之前自动发送一个预检请求。 只有在预检请求的结果OK后才会发起真正的请求。

预检请求官方文档https://developer.mozilla.org/zh-CN/docs/Glossary/Preflight_request

vue axios中何时会触发预检请求?

结果试验,在使用axios框架的情况下, 只要是非get请求, 且使用axios中的 data 发送了请求的数据, 浏览器就会认为是非简单请求, 就会在真正请求发起之前自动发送一个预检请求来确定服务器是否支持相应的请求。

vue axios中的请求

解决方法

目前网上大部分的所谓的解决方案是使用一个 叫qs框架(这个东西的作用就是将我们的data请求数据转换为url参数, 从而将POST data请求转换为简单请求), 其实这样做是非常不靠谱的方式,首先在请求参数较多时请求直接无法正常运行, 其次请求参数每次请求执行都会进行二次转换费时费力,白白浪费系统资源,还有降低了网络请求数据的私密性,有数据安全风险等。

正确的解决方法

在服务端针对前端浏览器发送的预检请求(即请求方式为 OPTIONS 的请求)做出相应的回应, 

例如,客户端可能会在实际发送 DELETE 请求之前,先向服务器发起预检请求,用于询问是否可以向服务器发起 DELETE 请求:

HTTP

OPTIONS /resource/foo
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: origin, x-requested-with
Origin: https://foo.bar.org

如果服务器允许,那么服务器就会响应这个预检请求。并且其响应标头 Access-Control-Allow-Methods 会将 DELETE 包含在其中:

HTTP

HTTP/1.1 200 OK
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: https://foo.bar.org
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 86400

gin框架中的预检请求回应示例

在gin框架中,我们可以有2种方式对预检请求进行回应:

1. 针对每个非GET的路由都增加一个OPTIONS的路由, 将他们统一指向一个专门来处理预检请求的函数或者方法。

2. 使用gin路由中的 r.NoRoute方法将所有的非路由请求都指向我们设定的专门处理预检请求的函数或者方法中, 然后再这个方法中通过请求方式 OPTIONS来统一处理预检请求, 非OPTIONS请求则当做404请求处理。

// 统一处理预检请求 和没有路由的请求
func NoRouteHandler(c *ginx.XContext) {
	origin := c.Request.Header.Get("Origin")
	// 获取当前请求方式
	method := c.Request.Method
	// 如是预检请求直接终止当前请求并返回状态为ok
	if method == "OPTIONS" {
		// 这个是响应给预检请求的头信息,这个必须包含Access-Control-Allow-Origin 否则CORS不通过!!!
		c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
		// 预检允许的请求头信息, 注意必须包含
		c.Writer.Header().Set("Access-Control-Allow-Headers",“Accept, Accept-Language, Content-Language, Content-Type, Range, origin, Authorization, Token, X-Token, AccessToken”)
		// CORS预检响应缓存 预检响应缓存时间 86400 秒 即1天
		c.Writer.Header().Set("Access-Control-Max-Age", "86400")
		// 退出gin请求链路并返回OK状态
		c.AbortWithStatus(http.StatusOK) // 这个很关键 告诉浏览器预检成功了
		return
	}

	// 其他情况处理。。。。。。
}

总结: 当我们在后端设置了CORS跨域后,正常的在CORS白名单中的请求都可以正常通过CORS跨域请求, 当遇到非简单请求时我们通过普通方式设置的CORS就失效了,即造成了 GET可以跨域请求, POST,put, delete, path请求方式是不能跨越请求的尴尬。 这时候就需要设置专门的预检请求响应来解决相关的问题了。另外在预检请求响应时设置的允许和暴露的头信息中必须有 Content-Type 头信息,否则预检不通过还是会被CORS阻止请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值