今天来记录一下关于ajax跨域的一些问题。以备不时之需。
跨域
同源策略限制
同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。
解决方式
通常来说,比较通用的有如下两种方式,一种是从服务器端下手,另一种则是从客户端的角度出发。二者各有利弊,具体要使用哪种方式还需要具体的分析。
- 服务器设置响应头
- 服务器代理
- 客户端采用脚本回调机制。
方式一
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()"> <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>
同级目录下的test1.PHP内容如下:
<"It Works."; "text-align: center">跨域请求
刚才是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()"> <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"<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()"> <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"<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应该帮助我们实现数据请求这个过程,把“小红的联系方式”要到手,并返回给“小明”。
<"" alt="代理模式下的跨域实现" src="/UploadFiles/2021-04-02/201706210828518.gif">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="/UploadFiles/2021-04-02/jquery-1.8.0.js"><"jsonpcallback(".$result.")"; "" alt="JSONP原生跨域实现" src="//img.jbzj.com/file_images/article/201706/201706210828529.gif">JQuery方式实现
采用原生的JavaScript需要处理的事情还是蛮多的,下面为了简化操作,决定采用jQuery来代替一下。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ajax 测试</title> <script src="/UploadFiles/2021-04-02/jquery-1.8.0.js">相应的,test1.php为了配合客户端聊天的需求,也稍微做了点改变。
<"http://api.qingyunke.com/api.php"); // 拼接一些字符串 echo $requestparam . "($result)"; "" alt="JSONP 跨域实现聊天应用" src="/UploadFiles/2021-04-02/2017062108285210.gif">总结
至此,关于简单的ajax跨域问题,就算是解决的差不多了。对我个人而言,对于这三种方式有一点点自己的看法。
- 服务器设置Access-Control-Allow-Origin的方式适合信用度高的小型应用或者个人应用。
- 代理模式则比较适合大型应用的处理。但是需要一个统一的规范,这样管理和维护起来都会比较方便。
- JSONP方式感觉还是比较鸡肋的(有可能是我经验还不足,没认识到这个方式的优点吧(⊙﹏⊙)b)。自己玩玩知道有这么个东西好了。维护起来实在是优点麻烦。
参考链接:
Ajax跨域请求: https://www.jb51.net/article/72703.htm
服务器端跨域设置: https://www.jb51.net/article/104442.htm
Ajax高级笔记: https://www.jb51.net/article/116878.htm
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!暂无评论...
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]