跨域是什么?
跨域就是一个资源请求与其不在同一个域(源)的资源,不在同一个域(源)是指两个域的协议、域名或端口不同。出于安全考虑,浏览器会限制某些跨域请求,哪些限制哪些不限制,这就是同源策略。
一个标准的跨域请求过程是怎样的?
上面说到,同源策略并不会限制所有的跨域请求,对于符合放行条件的请求,其请求过程是与普通请求无异的。至于哪些请求符合放行条件,一定要认真看一下HTTP访问控制——简单请求 及 同源策略——跨源网络访问
对于不符合直接放行的请求,浏览器会首先发送一个预验请求(Preflighted requests)到被请求的资源,来确定当前的源是否允许发送该请求。预验通过之后,真实的请求才会发送。流程如下:

另外说明一下,预验请求使用OPTION方法。
解决跨域问题的思路
当我们的跨域请求被同源策略阻止时,跨域问题就产生了。同源策略允许某些安全的跨域请求,也允许网站后台通过请求头定义哪些源可以跨域访问其资源,这是解决跨域问题的两个着手点。当然,有些工具可以关闭浏览器的同源策略,同样也可以让你不受跨域问题的困扰,但是这种方法只能用来调试,并非长久之计。
前端解决跨域问题的方法
第一种,就是前端调整HTTP请求,使它成为一个简单请求。一个简单请求要满足以下所有条件:
只能使用GET、HEAD或POST请求方法
不得手动设置以下头之外的头
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-type为application/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)
</script>