ajax跨域问题解决方案

今天来记录一下关于ajax跨域的一些问题。以备不时之需。

跨域

同源策略限制

同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。

解决方式

通常来说,比较通用的有如下两种方式,一种是从服务器端下手,另一种则是从客户端的角度出发。二者各有利弊,具体要使用哪种方式还需要具体的分析。

  • 服务器设置响应头
  • 服务器代理
  • 客户端采用脚本回调机制。

方式一

Access-Control-Allow-Origin 关键字只有在服务器端进行设置才

会生效。也就是说即使再客户端使用

xmlhttprequest.setHeaderREquest(‘xx‘,‘xx‘);
  • 1
  • 1

也不会有什么效果。

正常ajax请求

下面来模拟一下ajax非跨域请求的案例实现。

test1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ajax 测试</title>
</head>
<body>

<input type="button" value="Test" onclick="crossDomainRequest()">
<div id="content"></div>
<script>
    var xhr = new XMLHttpRequest();
    var url = ‘http://localhost/learn/ajax/test1.php‘;

    function crossDomainRequest() {
        document.getElementById(‘content‘).innerHTML = "<font color=‘red‘>loading...</font>";
        // 延迟执行
        setTimeout(function () {
            if (xhr) {
                xhr.open(‘GEt‘, url, true);
                xhr.onreadystatechange = handle_response;
                xhr.send(null);
            } else {
                document.getElementById(‘content‘).innerText = "不能创建XMLHttpRequest对象";
            }
        }, 3000);
    }

    function handle_response() {
        var container = document.getElementById(‘content‘);
        if (xhr.readyState == 4) {
            if (xhr.status == 200 || xhr.status == 304) {
                container.innerHTML = xhr.responseText;
            } else {
                container.innerText = ‘不能跨域请求‘;
            }
        }
    }
</script>

</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

同级目录下的test1.PHP内容如下:

<?php

echo "It Works.";

?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

跨域请求

刚才是HTML文件和php文件都在Apache的容器下,所以没有出现跨域的情形,现在把HTML文件放到桌面上,这样再次请求PHP数据的话,就营造了这样一个“跨域请求”了。

注意看浏览器的地址栏信息

再次进行访问,发现会出现下面的错误信息。

针对这种情况,比较常见的一个操作就是设置Access-Control-Allow-Origin

格式: Access-Control-Allow-Origin: domain.com/xx/yy.*

如果知道客户端的域名或者请求的固定路径,则最好是不使用通配符的方式,来进一步保证安全性。如果不确定,那就是用*通配符好了。

后端开发语言为PHP的时候可以再文件开始处这么设置:

header("Access-Control-Allow-Origin: *");
  • 1
  • 2
  • 1
  • 2

如果是ASPX页面的话,要这么设置(Java与之类似):

Response.AddHeader("Access-Control-Allow-Origin", "*");
  • 1
  • 1

这时,再次来访问一下刚才的路径。

服务器代理模式

这种方式应该算是比较常用的,而且被广泛采纳的一个方式了。说代理有点太过于书面化了,其实就是传话儿的。来举个小例子:

小明喜欢三班一个叫小红的女孩儿,但是不好意思去要人家的QQ,微信号。然后就托和自己班的女生–小兰。来帮自己去要。所以小兰就相当于一个代理。帮助小明获取原本不能直接获取的小红的联系方式。

下面来举个例子说明这个问题。

直接的跨域请求

修改一下刚才的URL即可,让ajax直接去请求其他网站的数据。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ajax 测试</title>
</head>
<body>

<input type="button" value="Test" onclick="crossDomainRequest()">
<div id="content"></div>
<script>
    var xhr = new XMLHttpRequest();
//    var url = ‘http://localhost/learn/ajax/test1.php‘;
     var url = ‘http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E5%93%92%E5%93%92‘;
    function crossDomainRequest() {
        document.getElementById(‘content‘).innerHTML = "<font color=‘red‘>loading...</font>";
        // 延迟执行
        setTimeout(function () {
            if (xhr) {
                xhr.open(‘GEt‘, url, true);
                xhr.onreadystatechange = handle_response;
                xhr.send(null);
            } else {
                document.getElementById(‘content‘).innerText = "不能创建XMLHttpRequest对象";
            }
        }, 3000);
    }

    function handle_response() {
        var container = document.getElementById(‘content‘);
        if (xhr.readyState == 4) {
            if (xhr.status == 200 || xhr.status == 304) {
                container.innerHTML = xhr.responseText;
            } else {
                container.innerText = ‘不能跨域请求‘;
            }
        }
    }
</script>

</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

结果如下:

启用代理模式

刚才的HTML页面,咱们还是用自己的接口:

url = ‘http://localhost/learn/ajax/test1.php‘;
  • 1
  • 1

具体如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ajax 测试</title>
</head>
<body>

<input type="button" value="Test" onclick="crossDomainRequest()">
<div id="content"></div>
<script>
    var xhr = new XMLHttpRequest();
    var url = ‘http://localhost/learn/ajax/test1.php‘;
//     var url = ‘http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E5%93%92%E5%93%92‘;
    function crossDomainRequest() {
        document.getElementById(‘content‘).innerHTML = "<font color=‘red‘>loading...</font>";
        // 延迟执行
        setTimeout(function () {
            if (xhr) {
                xhr.open(‘GEt‘, url, true);
                xhr.onreadystatechange = handle_response;
                xhr.send(null);
            } else {
                document.getElementById(‘content‘).innerText = "不能创建XMLHttpRequest对象";
            }
        }, 3000);
    }

    function handle_response() {
        var container = document.getElementById(‘content‘);
        if (xhr.readyState == 4) {
            if (xhr.status == 200 || xhr.status == 304) {
                container.innerHTML = xhr.responseText;
            } else {
                container.innerText = ‘不能跨域请求‘;
            }
        }
    }
</script>

</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

然后对应的test1.php应该帮助我们实现数据请求这个过程,把“小红的联系方式”要到手,并返回给“小明”

<?php

$url = ‘http://api.qingyunke.com/api.php?key=free&appid=0&msg=hello%20world.‘;
$result = file_get_contents($url);
echo $result;

?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

下面看下代码执行的结果。


jsonp方式

JSONP(JSON with Padding) 灵感其实源于在HTML页面中script标签内容的加载,对于script的src属性对应的内容,浏览器总是会对其进行加载。于是:

克服该限制更理想方法是在 Web 页面中插入动态脚本元素,该页面源指向其他域中的服务 URL
并且在自身脚本中获取数据。脚本加载时它开始执行。该方法是可行的,因为同源策略不阻止动态脚本插入,并且将脚本看作是从提供 Web
页面的域上加载的。但如果该脚本尝试从另一个域上加载文档,就不会成功。

实现的思路就是:

在服务器端组装出客户端预置好的json数据,通过回调的方式传回给客户端。

原生实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ajax 测试</title>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>
</head>
<body>
<input type="text" name="talk" id="talk">
<input type="button" value="Test" id="btn">
<div id="content"></div>
<script type="text/javascript">

function jsonpcallback(result) {
    for(var i in result) {
        alert(i+":"+result[i]);
    }
 }
 var JSONP = document.createElement("script");
 JSONP.type=‘text/javascript‘;
 JSONP.src=‘http://localhost/learn/ajax/test1.php?callback=jsonpcallback‘;
 document.getElementsByTagName(‘head‘)[0].appendChild(JSONP);

</script>

</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

服务器端test1.php内容如下:

<?php

$arr = [1,2,3,4,5,6];
$result = json_encode($arr);
echo "jsonpcallback(".$result.")";

?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

需要注意的是最后组装的返回值内容。

来看下最终的代码执行效果。

JQuery方式实现

采用原生的JavaScript需要处理的事情还是蛮多的,下面为了简化操作,决定采用jQuery来代替一下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ajax 测试</title>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>
</head>
<body>
<input type="text" name="talk" id="talk">
<input type="button" value="Test" id="btn">
<div id="content"></div>

<script type="text/javascript">

    function later_action(msg) {
        var element = $("<div><font color=‘green‘>"+msg+"</font><br /></div>");
        $("#content").append(element);
    }

    $("#btn").click(function(){
        // alert($("#talk").val());
        $.ajax({
        url: ‘http://localhost/learn/ajax/test1.php‘,
        method: ‘post‘,
        dataType: ‘jsonp‘,
        data: {"talk": $("#talk").val()},
        jsonp: ‘callback‘,
        success: function(callback){
            console.log(callback.content);
            later_action(callback.content);
        },
        error: function(err){
            console.log(JSON.stringify(err));

        },
    });
    });
</script>

</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

相应的,test1.php为了配合客户端聊天的需求,也稍微做了点改变。

<?php
$requestparam = isset($_GET[‘callback‘])?$_GET[‘callback‘]:‘callback‘;

// 青云志聊天机器人接口: http://api.qingyunke.com/api.php?key=free&appid=0&msg=hello
// 接收来自客户端的请求内容
$talk = $_REQUEST[‘talk‘];
$result = file_get_contents("http://api.qingyunke.com/api.php?key=free&appid=0&msg=$talk");

// 拼接一些字符串
echo $requestparam . "($result)";

?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

最后来查看一下跨域的效果吧。

时间: 2024-10-23 23:29:32

ajax跨域问题解决方案的相关文章

PHP Ajax 跨域问题解决方案

本文通过设置Access-Control-Allow-Origin来实现跨域. 例如:客户端的域名是client.0751.tv,而请求的域名是server.0751.tv. 如果直接使用ajax访问,会有以下错误: XMLHttpRequest cannot load http://server.0751.tv/server.php. No 'Access-Control-Allow-Origin' header is present on the requested resource.Ori

No &#39;Access-Control-Allow-Origin&#39; Ajax跨域访问解决方案

No 'Access-Control-Allow-Origin' header is present on the requested resource. 当使用ajax访问远程服务器时,请求失败,浏览器报如上错误.这是出于安全的考虑,默认禁止跨域访问导致的. 一.什么是跨域访问 举个栗子:在A网站中,我们希望使用Ajax来获得B网站中的特定内容.如果A网站与B网站不在同一个域中,那么就出现了跨域访问问题.你可以理解为两个域名之间不能跨过域名来发送请求或者请求数据,否则就是不安全的.跨域访问违反

[转]No &#39;Access-Control-Allow-Origin&#39; header is present on the requested resource.&#39;Ajax跨域访问解决方案

原 https://blog.csdn.net/zhoucheng05_13/article/details/53580683 No 'Access-Control-Allow-Origin' header is present on the requested resource. 什么是跨域访问 举个栗子:在A网站中,我们希望使用Ajax来获得B网站中的特定内容.如果A网站与B网站不在同一个域中,那么就出现了跨域访问问题.你可以理解为两个域名之间不能跨过域名来发送请求或者请求数据,否则就是不安

Ajax跨域与解决方案

1.同步交互与异步交互 同步交互:用户在URL地址输入http://www.baidu.com,服务器接收请求并进行相应处理,此时用户无法操作,只能等待,只有当返回数据到客户端的时候,用户才能继续操作异步交互:用户操作某个页面,请求某个数据,客户可以继续操作(服务器返回数据),不涉及到整个页面的刷新 2.XmlHttp XmlHttp是一套可以在Javascript.VbScript.Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API.XmlHttp最大的用处是可

Ajax跨域请求解决方案——jsonp

转自:http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html 1.一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨域请求,一律不准: 2.不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>.<im

ajax跨域请求解决方案

大家好,今天我们学习了js的跨域请求的解决方案,由于JS中存在同源策略,当请求不同协议名,不同端口号.不同主机名下面的文件时,将会违背同源策略,无法请求成功!需要进行跨域处理! 方案一.后台PHP进行设置, 前台无需任何设置,在后台被请求的PHP文件中,写入一条header header("Access-Control-Allow-Origin:*"); 表示允许那些域名请求这个PHP文件*表示所有域名都允许 这是最佳的解决方案,因为是在后台进行设置,不对外公开,所以更加安全, 方案二

AJAX 跨域 CORS 解决方案

本篇文章由:http://xinpure.com/solutions-for-cross-domain-ajax-cors/ 两种跨域方法 在 Javascript 中跨域访问是比较常见的事情 就像现在比较流行写单页应用,而单页应用在访问 API 的时候就会有跨域的问题 要解决跨域的问题,其实也并不复杂,有两种方案可以选择 Jsonp 跨域 Jsonp 的实现原理就是:创建一个回调函数,然后在远程服务上调用这个函数并且将 JSON 数据形式作为参数传递,完成回调. CORS(跨域资源共享) 跨源

ajax 跨域请求解决方案

response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Allow-Credentials","true&qu

【JS】AJAX跨域-被调用方与调用方解决方案(二)

解决跨域问题 跨域问题说明,参考[JS]AJAX跨域-JSONP解决方案(一) 实例,使用上一章([JS]AJAX跨域-JSONP解决方案(一))的实例 解决方案三(被调用方支持跨域) 被调用方解决,基于支持跨域的解决思路,基于Http协议关于跨域的相关规定,在响应头里增加指定的字段告诉浏览器,允许调用 跨域请求是直接从浏览器发送到被调用方,被调用方在响应头里增加相关信息,返回到页面,页面能正常获取请求内容. 1.服务端增加一个过滤器(CrossFilter.java),过滤所有请求,在请求响应