跨域问题及其前后端解决办法

来源:互联网 发布:电脑程序员图片 编辑:程序博客网 时间:2024/06/05 08:21

跨域是什么?

跨域就是一个资源请求与其不在同一个域(源)的资源,不在同一个域(源)是指两个域的协议、域名或端口不同。出于安全考虑,浏览器会限制某些跨域请求,哪些限制哪些不限制,这就是同源策略。

一个标准的跨域请求过程是怎样的?

上面说到,同源策略并不会限制所有的跨域请求,对于符合放行条件的请求,其请求过程是与普通请求无异的。至于哪些请求符合放行条件,一定要认真看一下HTTP访问控制——简单请求 及 同源策略——跨源网络访问

对于不符合直接放行的请求,浏览器会首先发送一个预验请求(Preflighted requests)到被请求的资源,来确定当前的源是否允许发送该请求。预验通过之后,真实的请求才会发送。流程如下:

这里写图片描述

(图片来自:https://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server)

另外说明一下,预验请求使用OPTION方法。

解决跨域问题的思路

当我们的跨域请求被同源策略阻止时,跨域问题就产生了。同源策略允许某些安全的跨域请求,也允许网站后台通过请求头定义哪些源可以跨域访问其资源,这是解决跨域问题的两个着手点。当然,有些工具可以关闭浏览器的同源策略,同样也可以让你不受跨域问题的困扰,但是这种方法只能用来调试,并非长久之计。

前端解决跨域问题的方法

第一种,就是前端调整HTTP请求,使它成为一个简单请求。一个简单请求要满足以下所有条件:

  • 只能使用GETHEADPOST请求方法

  • 不得手动设置以下头之外的头

    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width
  • Content-Type只能是下面的一种

    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

前端开发人员可以检查自己发出的请求,修改以符合上述要求,就能解决跨域问题。比如 angular resource的save方法,它会发出一个POST请求,content-typeapplication/json,这就会触发预验请求,如果后端不相应处理的话,就会产生跨域问题。而不同的,Jquery发送POST请求,就会默认吧content-type设置为application/x-www-form-urlencoded,就没有跨域问题。所以,有时候同一个请求,用angular来发出就有跨域问题,用Jquery发出就没有,原因就在这。

需要注意的是,改变content-type可能会导致后端解析数据出错,content-type:application/x-www-form-urlencoded,参数是以键值对形式保存的,所以后端会做自动解析操作,而content-type: text/plain,参数的形式就不确定了,只能以原始数据流的方式保存(放在PayLoad里面),需要自己解析。详情请看 AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式

除了改变请求本身之外,JSONP也是一种绕过跨域问题的办法,这是因为浏览器不限制加载嵌在<script>标签中跨域的js文件,所以可以通过动态生成js文件内容来返回数据。

后端解决跨域问题

后端可以设置Access-Control-XXX请求头来允许某个源对其跨域请求。图示如下:

这里写图片描述

具体看:Server-Side Access Control (CORS)

原创粉丝点击