同源策略
同源指的是域名(或IP),协议,端口都相同,不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对方的资源。
同源的判定:
以http://www.example.com/dir/page.html
为例,
以下表格指出了不同形式的链接是否与其同源:
(原因里未申明不同的属性即说明其与例子里的原链接对应的属性相同)
什么是跨域?
顾名思义,跨域就是不同的域名下的资源访问,会被浏览器的本地安全策略阻止,例如www.uedsc.com去AJAX请求一个wenda.uedsc.com的资源,他们实际上是不同的两个二级域名,顶级域名是uedsc.com,就会出现跨域访问问题。
下面的这张表格可以清晰解释那些属于跨域,那时不是属于跨域
是否允许跨域的判定
前文提到了同源策略的判定,然而同源策略在加强了安全的同时,对开发却是极大的不便利。因此开发者们又发明了很多办法来允许数据的跨域传输(常见的办法有JSONP
、CORS
)。当域名不同源的时候,由于跨域实现的存在,浏览器不能直接根据域名来判定跨域限制。那么浏览器具体又是如何实现判定的呢?看下面的例子。
跨域的判定流程
-
浏览器先根据同源策略对前端页面和后台交互地址做匹配,若同源,则直接发送数据请求;若不同源,则发送跨域请求。
-
服务器解析程序收到浏览器跨域请求后,根据自身配置返回对应文件头。若未配置过任何允许跨域,则文件头里不包含
Access-Control-Allow-origin
字段,若配置过域名,则返回Access-Control-Allow-origin
+对应配置规则里的域名的方式
。 -
浏览器根据接受到的http文件头里的
Access-Control-Allow-origin
字段做匹配,若无该字段,说明不允许跨域;若有该字段,则对字段内容和当前域名做比对,如果同源,则说明可以跨域,浏览器发送该请求;若不同源,则说明该域名不可跨域,不发送请求
(但是不能仅仅根据服务器返回的文件头里是否包含Access-Control-Allow-origin
来判断其是否允许跨域,因为服务器端配置多域名跨域的时候,也会出现不能跨域的域名返回包里没有Access-Control-Allow-origin
字段的情况。下文配置说明里会讲。)
配置服务器实现跨域传输
前面讲到了同源策略的基本判定,以及浏览器实现跨域判断的方式,那么,如何在服务器端做配置来允许跨域传输呢?下文将以Nginx为例,讲一下三种情况下的配置。
配置项解析
CORS常用的配置项有以下几个
Access-Control-Allow-Origin(必含) – 允许的域名,只能填通配符或者单域名
-
Access-Control-Allow-Methods(必含) – 这允许跨域请求的http方法(常见有
POST
、GET
、OPTIONS
) -
Access-Control-Allow-Headers(当预请求中包含Access-Control-Request-Headers时必须包含) – 这是对预请求当中Access-Control-Request-Headers的回复,和上面一样是以逗号分隔的列表,可以返回所有支持的头部。
-
Access-Control-Allow-Credentials(可选) – 该项标志着请求当中是否包含cookies信息,只有一个可选值:true(必为小写)。如果不包含cookies,请略去该项,而不是填写false。这一项与XmlHttpRequest2对象当中的withCredentials属性应保持一致,即withCredentials为true时该项也为true;withCredentials为false时,省略该项不写。反之则导致请求失败。
-
Access-Control-Max-Age(可选) – 以秒为单位的缓存时间。预请求的的发送并非免费午餐,允许时应当尽可能缓存。
具体配置举例
全域名或者单域名允许跨域
添加的域名必须带http://
协议头(否则服务器无法区分是http还是https),
如果接受所有域名的跨域请求,则可以用 *
(安全性有问题,不推荐)
-
'Access-Control-Allow-Methods' 允许多参数,'Access-Control-Allow-origin'不允许多参数,所以只能是条件语句判断要不要加这个。这也是我前面提到的为什么即使HTTP文件头返回值里没有'Access-Control-Allow-origin',也不能说明它就是不允许跨域的。
-
nginx配置文件的
http
配置部分不能用if
条件语句,所以多域名的时候必须加在local
部分内。另外加在local
内的只对对应的服务器域名做跨域请求的配置,加在http
里会让跑在该nginx下的所有网站都统一采取这种配置。 -
Access-Control-Allow-Origin
也可以改成全小写的形式,不影响结果.(access-control-allow-origin
也可以)
本文引自:https://blog.csdn.net/evilstar2015/article/details/52459075
跨域相关问题解决