最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

ajax跨域问题完美解决方法

来源:懂视网 责编:小采 时间:2020-11-27 19:52:12
文档

ajax跨域问题完美解决方法

ajax跨域问题完美解决方法:这次给大家带来ajax跨域问题完美解决方法,ajax跨域问题解决的注意事项有哪些,下面就是实战案例,一起来看一下。今天来记录一下关于ajax跨域的一些问题。以备不时之需。跨域同源策略限制同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也
推荐度:
导读ajax跨域问题完美解决方法:这次给大家带来ajax跨域问题完美解决方法,ajax跨域问题解决的注意事项有哪些,下面就是实战案例,一起来看一下。今天来记录一下关于ajax跨域的一些问题。以备不时之需。跨域同源策略限制同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也
这次给大家带来ajax跨域问题完美解决方法,ajax跨域问题解决的注意事项有哪些,下面就是实战案例,一起来看一下。

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

跨域

同源策略限制

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

解决方式

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

  1. 服务器设置响应头

  2. 服务器代理

  3. 客户端采用脚本回调机制。

方式一

Access-Control-Allow-Origin 关键字只有在服务器端进行设置才
会生效。也就是说即使再客户端使用

xmlhttprequest.setHeaderREquest('xx','xx');

也不会有什么效果。

正常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()">
<p id="content"></p>
<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>

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

<?php
echo "It Works.";
?>

正常ajax请求

跨域请求

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

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

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

跨域出现了问题

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

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

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

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

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

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

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

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

服务器端跨域设置

服务器代理模式

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

小明喜欢三班一个叫小红的女孩儿,但是不好意思去要人家的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()">
<p id="content"></p>
<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>

结果如下:

代理模式下直接跨域会失败

启用代理模式

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

url = 'http://localhost/learn/ajax/test1.php';

具体如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>ajax 测试</title>
</head>
<body>
<input type="button" value="Test" onclick="crossDomainRequest()">
<p id="content"></p>
<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>

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

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

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

代理模式下的跨域实现

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">
<p id="content"></p>
<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>

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

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

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

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

JSONP原生跨域实现

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">
<p id="content"></p>
<script type="text/javascript">
 function later_action(msg) {
 var element = $("<p><font color='green'>"+msg+"</font><br /></p>");
 $("#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>

相应的,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)";
?>

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

JSONP 跨域实现聊天应用

总结

至此,关于简单的ajax跨域问题,就算是解决的差不多了。对我个人而言,对于这三种方式有一点点自己的看法。

  1. 服务器设置Access-Control-Allow-Origin的方式适合信用度高的小型应用或者个人应用。

  2. 代理模式则比较适合大型应用的处理。但是需要一个统一的规范,这样管理和维护起来都会比较方便。

  3. JSONP方式感觉还是比较鸡肋的(有可能是我经验还不足,没认识到这个方式的优点吧(⊙﹏⊙)b)。自己玩玩知道有这么个东西好了。维护起来实在是优点麻烦。

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

详细解析JS中Ajax的使用技巧

JQuery调用Ajax加载图片

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文档

ajax跨域问题完美解决方法

ajax跨域问题完美解决方法:这次给大家带来ajax跨域问题完美解决方法,ajax跨域问题解决的注意事项有哪些,下面就是实战案例,一起来看一下。今天来记录一下关于ajax跨域的一些问题。以备不时之需。跨域同源策略限制同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top