zoukankan      html  css  js  c++  java
  • 跨域问题出现原因和解决方案

    一、出现原因

    跨域是指a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,或是a页面为ip地址,b页面为域名地址,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。

    例如:

    URL 说明 是否跨域
    http://www.a.com/lab/a.js
    http://www.a.com/script/b.js
    同域名下不同文件
    http://www.cnblogs.com/a.js 
    http://www.a.com/b.js
    不同域名
    http://www.a.com:8000/a.js 
    http://www.a.com/b.js
    同域名下不同端口
    http://www.a.com/a.js 
    https://www.a.com/b.js
    同域名 不同协议
    http://www.a.com/a.js 
    http://70.32.92.74/b.js
    域名和域名对应ip
    http://www.a.com/a.js 
    http://script.a.com/b.js
    主域名相同 子域名不同
    http://www.a.com/a.js 
    http://a.com/b.js
    同一域名,不同二级域名(同上)

    二、解决方案

    【策略一】:Jsonp:需要目标服务器配合一个callback函数

    JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
    Json+padding(内填充),顾名思义,就是把JSON填充到一个盒子里,它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
    首先,网页动态插入<script>元素,由它向跨源网址发出请求。

    JSONP的产生:

    1.AJAX直接请求普通文件存在跨域无权限访问的问题,不管是静态页面也好.
    2.不过我们在调用js文件的时候又不受跨域影响,比如引入jquery框架的,或者是调用相片的时候
    3.凡是拥有scr这个属性的标签都可以跨域例如<script><img><iframe>
    4.如果想通过纯web端跨域访问数据只有一种可能,那就是把远程服务器上的数据装进js格式的文件里.
    5.而json又是一个轻量级的数据格式,还被js原生支持
    6.为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback 参数给服务端

    Js 客户端 方案一:

    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />  
    <script type="text/javascript">  
        function jsonpCallback(result) {  
            //alert(result);  
            for(var i in result) {  
                alert(i+":"+result[i]);//循环输出a:1,b:2,etc.  
            }  
        }  
        var JSONP=document.createElement("script");  
        JSONP.type="text/javascript";  
        JSONP.src="http://crossdomain.com/services.php?callback=jsonpCallback";  
        document.getElementsByTagName("head")[0].appendChild(JSONP);  
    </script> 

    Js 客户端 方案二:

    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />  
    <script type="text/javascript">  
        function jsonpCallback(result) {  
            alert(result.a);  
            alert(result.b);  
            alert(result.c);  
            for(var i in result) {  
                alert(i+":"+result[i]);//循环输出a:1,b:2,etc.  
            }  
        }  
    </script>  
    <script type="text/javascript" src="http://crossdomain.com/services.php?callback=jsonpCallback"></script>

    Jquery 客户端 方案一:

    <script type="text/javascript" src="jquery.js"></script>  
    <script type="text/javascript">  
        $.getJSON("http://crossdomain.com/services.php?callback=?",  
        function(result) {  
            for(var i in result) {  
                alert(i+":"+result[i]);//循环输出a:1,b:2,etc.  
            }  
        });  
    </script> 

    Jquery 客户端 方案二:

    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
        $.ajax({
            url:"http://crossdomain.com/services.php",
            type:'get',//注意:跨域请求是只能是get请求不能使用post请求
            dataType:'jsonp',
            data:'',
            jsonp:'callback',//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback)
            jsonpCallback:"success",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
            success:function(result) {
                console.log(result);
            },
            timeout:3000
        });
    </script>

    Jquery 客户端 方案三:

    <script type="text/javascript" src="jquery.js"></script>  
    <script type="text/javascript">  
        $.get('http://crossdomain.com/services.php?callback=?', {name: encodeURIComponent('tester')}, function (json) { for(var i in json) alert(i+":"+json[i]); }, 'jsonp');  
    </script>

     PHP 服务端:

    //服务端返回JSON数据
    $arr=array('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
    $result=json_encode($arr);
    //动态执行回调函数
    $callback=$_GET['callback'];
    echo $callback."($result)";

    【策略二】基于iframe实现的跨子域:通过修改document.domain来跨子域

    将子域和主域的document.domain设为同一个主域.前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域
    主域相同的使用document.domain

    【策略三】PHP设置header头来实现跨域

    //Access-Control-Allow-Origin:指定允许其他域名访问。该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
    header('Access-Control-Allow-Origin:*');
    //Access-Control-Allow-Methods:响应类型
    header('Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS');
    //Access-Control-Allow-Headers:响应头设置
    header('Access-Control-Allow-Headers:X-Requested-With,Content-Type');
    //Access-Control-Expose-Headers:该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
    header('Access-Control-Expose-Headers:Authorization');
  • 相关阅读:
    R语言:用简单的文本处理方法优化我们的读书体验
    R语言-用R眼看琅琊榜小说的正确姿势
    R语言-Kindle特价书爬榜示例 & 输出HTML小技巧
    Hadoop里的数据挖掘应用-Mahout——学习笔记<三>
    Hadoop-HBASE案例分析-Hadoop学习笔记<二>
    Hadoop概括——学习笔记<一>
    R语言——七月
    R语言:ggplot2精细化绘图——以实用商业化图表绘图为例
    R语言学习笔记之: 论如何正确把EXCEL文件喂给R处理
    R语言学习笔记-机器学习1-3章
  • 原文地址:https://www.cnblogs.com/jxl1996/p/10160544.html
Copyright © 2011-2022 走看看