跨域小计

这周,时间紧,手头遇到需要跨域解决的问题,就业务点遇到的问题展开一下跨域这件事。

跨域的产生,需根据主域、子域不同而处理方法各异。当然本质上最高效最安全为宜。

这次业务场景是:移动端web内容,发起请求的页面在 child1.parent.com,而服务接口所在的位置是child2.parent.com

显而易见,主域相同,子域不同,这事就好办多了。

接着咱们来看方案:
1、JSONP,大多数人会立即想到的方案,支持GET请求,论功能,用在此处没毛病,不过要改造接口。

2、iframe结合document.domain,刚好是同主域不同子域的情况,可以满足需求。
在 child1.parent.com/a.html 中,嵌入 iframe (src=”child2.parent.com/b.html”),并设置两个页面的document.domain = “parent.com”,接下来就是在a页面中调用b页面的方法了,比如document.querySelector(‘#iframe’).contentWindow.getData();。这种方式不需要变更接口,但需要产生页面嵌套和逻辑。

3、CORS(Cross-Origin Resource Sharing)标准早于14年就已经诞生,逐渐被现代浏览器完美支持。

CORS兼容性
CORS兼容性

因为本例是移动端项目,兼容性方面问题不大,功能覆盖率高于96%。
具体实现,需要在资源服务器Header设置一下Access-Control-Allow-Origin http://child1.parent.com
在PHP中:

header('Access-Control-Allow-Origin:http://child1.parent.com');
header('Access-Control-Allow-Methods:POST,GET');

客户端 XMLHttpRequest 方式

// http://child1.parent.com/request.html
let xhr =new XMLHttpRequest(); ;
    xhr.open('GET','http://child2.parent.com/api',true);
    xhr.onload =function() {
        console.log(xhr.response);
    };
    xhr.onerror =function() {
       console.error('error in request.');
    };
    xhr.send();

或者 客户端 fetch 请求

fetch('http://child2.parent.com/api', {
    method: 'POST',
    mode: 'cors', //支持cors, no-cors, same-origin 设置
    redirect: 'manual',
    headers: new Headers({
        //...
    })
}).then(function() {  });

以上只实现了对指定来源的访问,但需要注意的是区分协议头,如果是https的请求,应该设置 https://child1.parent.com。当然,也可以直接设置为Access-Control-Allow-Origin *,只是如此会降低一些访问的门槛,增加其他人访问的可能性。另外,CORS的跨域请求默认情况下不发送本地cookie,同时也不接受来自服务器的cookie。通过服务端配置Access-Control-Allow-Credentials:true ,客户端Ajax请求设置请求对象 xhr.withCredentials = true ; fetch请求需要添加credentials: ‘same-origin’ 即可实现。在此项目中并不需要使用。

综合以上,很显然CORS方法代码量改变是最小的,并且相对JSONP来说支持POST,适用范围更广,当选最终方案。

发表评论

电子邮件地址不会被公开。 必填项已用*标注