CORS跨域请求

1,318 阅读4分钟

前言

相信很多前端开发人员都会遇到跨域请求的问题。或者在面试的时候,都会被问到如何解决跨域问题,有多少人是觉得这个是前端必须要去解决的问题?实际上这个问题要前后端共同去解决的,我们常用的方法无论是用jsonp还是cors都是需要前后端一起去完成的。之所以写这篇文章就是最近在使用cors时,遇到了一些问题,在此进行总结一下加深印象。

项目情况

项目要求前后端需要部署在不同的域名或者是不同的端口下面,自然就会存在请求跨域的问题了,跟后台协商好用的解决方案是使用CORS方式。请求需要cookie,需要自定义请求头‘x-requested-with’,以下是后台设置的代码,正常这样设置是没问题的了

前端也设置了请求头 withCredentials = true;最后的结果还是不行,这就很奇怪了,百度看了很多解决方案都是一样的代码,为什么这里就不行?请求携带cookie或有自定义请求头,origin也动态设置成对应发出请求的origin了。

postman、fetch测试

在postman上使用同样的请求(无‘x-requested-with’请求头,也无cookie)切换method进行测试,只有get和post会有状态码返回,其他的连状态码都没有,看上图的设置,options和delete理应也会有状态码返回的才对,这是就判断是不是后台代码在哪个地方进行了拦截,连进CorsUtils的机会都没有。用fetch测试,带上‘x-requested-with’在控制台看到Request Method为OPTIONS,无响应体。另外在项目里测试的是一个post请求,携带了cookie和自定义请求头。接下来就了解下cors的存在的场景吧。

cors场景

cors存在三种跨域请求场景,分别是简单跨域请求带预检(Preflighted)的跨域请求附带身份凭证的请求

简单跨域请求

当满足以下条件时,浏览器会认为是简单请求

  • 请求方法是get,post或head,且Content-Type的值为application/x-www-form-urlencoded, multipart/form-data或着text/plain中的一个值;
  • 无自定义请求头

此时“Access-Control-Allow-Origin”设置成“*”,即可跨域访问,也可以设置成指定的域名,在上面所说的项目中也验证了这点,确实是可以跨域请求成功了。

带预检(Preflighted)的跨域请求

当满足以下任一条件时,浏览器会先发送一个OPTIONS的预检请求,当预检请求成功后,才会发送真正的请求

  • 请求方法是put、delete、connect、options、trace和patch其中之一;
  • content-type的值是application/x-www-form-urlencoded, multipart/form-data和text/plain之外的;
  • 携带自定义请求头的;

到这里,结合项目用的请求(就是这里所说的带预检的请求)和上面的测试情况,就让后台去检查他使用的后台框架是不是在哪里对get和post以外的请求拦截调了,后台去检查后果然是后台框架上做了限制,根本就没有机会进入到上图粘出来的程序。至于后台做了什么我就不是很懂了这里就略过了。

附带身份凭证的请求

另外项目需要做会话处理,需要使用到cookie,后台设置了“Access-Control-Allow-Credentials”为 true,前端也设置了请求头 withCredentials = true;这样请求就能把cookie带上了。这里要注意的是当请求需要附带身份凭证时,“Access-Control-Allow-Origin”要设置成指定域名,建议有跨域要求都设置成动态域名,不要设置“*”避免不必要的麻烦。

总结

以上是在开发过程中遇到的问题,针对这个问题的排查过程做了个回忆,并对cors跨域请求的知识做了个巩固。扎实的基础会对问题的排查节省很多时间,多总结,多积累。

如有错误的理解,烦请指出,谢谢阅读。