js 跨域的几种常见解决方案

来源:互联网 发布:企业数据备份方案 编辑:程序博客网 时间:2024/05/21 14:06

1. JSONP(JSON with Padding)

JSONP 技术的原理介绍

jsonp 的实现是基于html标签中src属性的数据源特性, 部分 html 标签比如 img script 可以通过 src 进行跨域访问,而浏览器不可能对这一行为进行阻止,虽然,浏览不支持js语言直接进行跨域http请求,但是我们可以间接的通过 src 属性从服务器返回一个 js 回调函数 从而实现跨域请求的目的

1. 简单的例子

浏览器端

       <script type="text/javascript">         // 1 定义一个带参数回调函数          function fn(data){             alert(data);          }       </script>        //2 通过 srcipt标签的 src 属性从服务器返回一个 fn(data)回调       <script src='http://www.test.com/jsonp/callJs.php'></script>

服务器 php 端

     <?php       // 3 返回一个在请求页里定义好的js函数,并把参数返回        echo "fn('你好')";

2. 简单封装

1封装JS函数
function jsonp(params) {//获取 head 标签var head = document.querySelector('head');//创建 script 标签var script = document.createElement('script');//创建回调函数var call = "fn" + new Date().getTime();window[call] = function(arg) {console.log(arg);params.success(arg);// alert(3);}//请求 参数中 url 地址 并将 回调函数做为参数添加到 url script.src = params.url + '?callback=' + call;head.appendChild(script);}
# 2 在 html 中引用
<script src="./jsonp.js" /></script><script type="text/javascript">    // 调用封装好的方法 并传递 url 和 请求成功后的回调函数    jsonp({        url: "http://www.longtaoge.com/jsonp/php/js.php",        success: function(repose) {            console.log(repose);            //处理数据            fillData(repose);        }    });</script>
3 php返回数据
<?php    //获取Get 请求中 jsop 的回调    $cal=!empty($_GET['callback'])?$_GET['callback']:'';    //从文件中读取数据并返回    $va=file_get_contents("../data/data.json");    //返回数据    echo $cal.'('.$va.')';    ?>

3. 模似封装 ajax

# 1 封装 ajax 函数
//声明一个对象function $() {}//模仿ajax 函数$.ajax = function(params) {//获取参数 请示地址 var url = params.url || location.pathname;var type = params.type || 'get'; //请求方式var data = params.data || {};  //获取请求参数var dataType = params.dataType; //jsonp//如果需要跨域 if (dataType == 'jsonp') {    var head = document.querySelector('head');    var script = document.createElement('script');    //模仿jQuery 的回调函数    var call = 'jQuery' + new Date().getTime();    url = url + '?callback=' + call;    if (type == "get") { // 通过Get 请求添加附加参数        url += "&"+dataFomart(data);        //清空参数        data = null;    }    //通过 script 标签的 src 属性 请求    script.src = url;    head.appendChild(script);    window[call] = function(arg) {        params.success(arg);    }    return;}//格式化请求参数function dataFomart(data) {    var strs = '';    for (var vl in data) {        strs += vl + '=' + data[vl] + '&';    }    console.log(strs);    return strs.slice(0, -1);}if (type == "get") {    url += '?' + dataFomart(data);    data = null;}// ajax var xhr = new XMLHttpRequest();xhr.open(type, url);if (type == "post") {    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');}xhr.send(dataFomart(data));xhr.onreadystatechange = function() {    if (xhr.readyState == 4 && xhr.status == 200) {        //解析为json         var str = JSON.parse(xhr.responseText);        params.success(str);    }}

};

2 在html 中引用自定义ajax
<script src='ajax.js'></script><script type="text/javascript">var btn = document.querySelector('.btn');btn.onclick = function() {    $.ajax({        url: 'http://www.longtaoge.com/jsonp/demo.php',        type: 'get',        data: { name: '小明', age: 12 },        dataType: 'jsonp',        success: function(data) {            console.log(data);           // 处理返回数据 fillData(data);        }    });}
3 服务器端返回数据
<?php    header("Content-type:text/json;charset=utf-8");   //获取回调方法   $cal=!empty($_GET['callback'])?$_GET['callback']:'';   //获取相关参数   $name=!empty($_REQUEST['name'])?$_REQUEST['name']:"";   $age=!empty($_REQUEST['age'])?$_REQUEST['age']:"";   //从文件中取出模似数据   $va=file_get_contents("./data/data.json");   $vaObj=json_decode($va);   //TODO 处理数据    if (empty($cal)) {       // 参数       echo  json_encode($vaObj);     }else{        // 跨域回调      echo $cal.'('.json_encode($vaObj).')';   }

2. CORS(Cross-origin resource sharing)

CORS是一个W3C标准,全称是”跨域资源共享” , cors 需要浏览器和服务器的支持,现在主流的浏览器均支持这一标准.
服务器端 需要对响应头进行相应的配置实现这一功能

举例说明:在网站 test.com 有一个向 www.longtaoge.com 发起的js简单请求http://www.test.com/cors/cors.html <script type="text/javascript">var xhr = new XMLHttpRequest;xhr.open('get', 'http://www.longtaoge.com/cors/cors.php');xhr.send();xhr.onreadystatechange = function() {    if (xhr.readyState == 4 && xhr.status == 200) {        console.log(xhr.responseText);        document.write(xhr.responseText);    }}</script>

直接请求浏览器将提示以下错误信息

cors.html:1 XMLHttpRequest cannot load http://www.homework.com/cors/cors.php. No 'Access-Control-Allow-Origin' header is present on the requested resource.Origin 'http://www.test.com' is therefore not allowed access.

http://www.longtaoge.com/cors/cors.php

可以在响应头中设置 Access-Control-Allow-Origin 实现跨域请求

<?php   header('Access-Control-Allow-Origin:http://www.test.com'); //允许 www.test.com 的跨域请求 //header('Access-Control-Allow-Origin:*');  //允许所有网站的跨域请求  echo "来自 www.homework.com  的数据 ";?>

再次访问
CORS

3. 配置apache反向代理实现浏览跨域

1 apache 配置

  • 打开配置文件httpd.conf
  • 开启 proxy_http_module 和 proxy_module 模块,将#号删除

         #LoadModule proxy_module modules/mod_proxy.so     #LoadModule proxy_http_module modules/mod_proxy_http.so
  • 代理详细配置

可以单独为某一个虚拟主机配置反向代理,这样不同的虚拟主机就可以被代理到不同的服务器了

  • 开启辅配置,将#号删除

    #Include conf/extra/httpd-vhosts.conf

  • 配置虚拟主机

    <VirtualHost *:80> ServerAdmin 61852263@qq.com DocumentRoot "E:/www/test" ServerName test.com #本服务器域名 ServerAlias www.test.com  ErrorLog "logs/dummy-host.studyit.com-error.log" CustomLog "logs/dummy-host.studyit.com-access.log" common ProxyRequests Off # 访问/api 相当于访问   http://www.longtaoge.com:80 ProxyPass /api http://www.longtaoge.com:80 # 这样所有的请求就经过 /api 被代理到  http://www.longtaoge.com:80了 # /api 也不是固定的,可以自行调整

2 html 访问接口

 <script type="text/javascript">    // 通过服务器代理 相当于访问 http://www.longtaoge.com/jsonp/demo.php     var url = '/api/jsonp/demo.php';     var xhr = new XMLHttpRequest();     xhr.open('get', url);     xhr.send();     xhr.onreadystatechange = function() {        if (xhr.readyState == 4 && xhr.status == 200) {            //解析为json             var str = JSON.parse(xhr.responseText);            console.log(str);         }     }     </script>

3 服务器返回数据

<?php header("Content-type:text/json;charset=utf-8");//模似数据$va=file_get_contents("./data/data.json");$vaObj=json_decode($va);//返回输出echo  json_encode($vaObj);