浏览器的跨域问题及其解决方法

跨域

由于浏览器的同源策略(请求的url地址,必须与浏览器上的url地址处于同一域上),不在同一域下的地址不能互相访问。同源是指,域名、协议、端口号都一致。

http://google.comhttps://google.com 不同,因为协议不同;
http://sina.com:8080http://sina.com:1000 不同,因为端口不同;
http://sina.com:8080https://google.com 不同,协议、域名、端口号都不同。

同源策略分为以下两种:
DOM同源策略:禁止对不同源页面DOM进行操作。这里主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。
XMLHttpRequest同源策略:禁止使用XHR对象向不同源的服务器地址发起HTTP请求。

跨域限制是为了安全性考虑。有了跨域的限制,我们访问页面就更加安全。如果没有同源策略,大家都可以随便通过ajax直接获取其他网站的信息,这样互联网就打乱了。

跨域的解决方法

<img>的src属性(获取图片),<link>的href属性(获取css),<script>的src属性(获取JavaScript)这三个都不符合同源策略,它们都可以跨域获取数据。

JSONP

JSONP,即JSON with padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议。

注意:JSONP只支持get请求,不支持post请求。

凡是拥有scr这个属性的标签都可以跨域,例如<script><img><iframe>

<script>是没有同源限制的,就是利用src属性能够跨域访问的特性,所以可以通过<script>访问目标地址,通过传入的回调函数callback对返回的数据进行处理并返回。

导入JSONP库,封装JSONP

import originJSONP from 'jsonp';

/**
 * @export
 * @param {String} url  跨域访问的地址
 * @param {Object|Function} data   传递的参数对象options / callback
 * @param {Function} option  回调函数,就可以拿到数据,用ES6开发,更常用的使用Promise方法而不是回调函数
 */

export default function jsonp(url, data, option) {
  url += (url.indexOf('?') < 0 ? '?' : '&') + param(data);
  return new Promise((resolve, reject) => {
    originJSONP(url, option, (err, data) => {
      if (!err) {
        resolve(data)
      } else {
        reject(err)
      }
    });
  });
}

function param(data) {
  let url = '';
  for (var k in data) {
    let value = data[k] !== undefined ? data[k] : '';
    url += `&${k}=${encodeURIComponent(value)}`;
  }
  return url ? url.substring(1) : '';
}

原生JS封装

function loadScript(xyUrl, callback){  
    var head = document.getElementsByTagName('head')[0];  
    var script = document.createElement('script');  
    script.type = 'text/javascript';  
    script.src = xyUrl;  

    script.onload = script.onreadystatechange = function(){  
        if((!this.readyState || this.readyState === "loaded" || this.readyState === "complete")){  
            callback && callback();  
            // Handle memory leak in IE  
            script.onload = script.onreadystatechange = null;//人工回收内存  
            if ( head && script.parentNode ) {  
                head.removeChild( script );  
            }  
        }  
    };  
    head.insertBefore( script, head.firstChild );  
}  

//  

var url = "http://todolist6.sinaapp.com/pages/QuickWayGetInfo.php?callback=showInfo";  

loadScript(url, showInfo);  

var showInfo = function(data){  
    console.log(data.name);  
}  

跨域资源共享CORS(Cross-origin resource sharing)

阮一峰老师的跨域资源共享CORS详解讲解得非常好,值得一看。

简单的说一下过程就是:
对于客户端,我们还是正常使用xhr对象发送ajax请求。
需要注意的是,我们需要设置我们的xhr属性withCredentials为true,这个属性是为了设置是否可以携带cookie,没有设置的话,cookie是带不过去的哦,设置: xhr.withCredentials = true;

对于服务器端,需要在 response header中设置如下两个字段:
Access-Control-Allow-Origin: http://www.yourhost.com
Access-Control-Allow-Credentials:true
这样,我们就可以跨域请求接口了。

代理

例如www.123.com/index.html需要调用www.456.com/server.php,可以写一个接口www.123.com/server.php,由这个接口在后端去调用www.456.com/server.php并拿到返回值,然后再返回给index.html,这就是一个代理的模式。相当于绕过了浏览器端,自然就不存在跨域问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值