本文主要探讨用于构建实时跨源通信的两个模块:跨文档消息通信(Cross Document Messaging)和XMLHttpRequestLevel2。通过这两个模块,我们可以构建不同域间进行安全通信的Web应用。
一、跨文档消息通信
出于安全方面的看的考虑,运行在同一浏览器中的框架、标签页、窗口间的通信一直多受到严格的限制。但是现实中还存在一些合理的让不同站点的内容能在浏览器内进行交互的需求,其中Mashup就是一个典型的例子,它是各种不同应用的结合体。为了满足上述需求,引入了一种新的功能:跨文档消息通信。其可以确保iframe、标签页、窗口间安全地进行跨源通信。
发送消息使用postMessage API,其示例代码如下:
chatFrame.contentWindow.postMessage(content,url);
接受消息时,需要在页面中添加一个事件处理函数,当消息到达时,通过检查消息的来源来决定如何对这条消息如何处理,示例代码如下:
window.addEventListener("message",messageHandler,true); function messageHandler(e){ switch(e.origin){//表示数据发送源 case "friend.example.com": //处理消息 processMessage(e.data);//发送方实际传送的消息 break; default: //其他消息来源 //消息被忽略。 } }
postMessage API提供了一种交互方式,使得不同源的iframe之间可以进行消息通信。
HTML5 通过引入源的感念对域安全进行了阐明和改进。源是网络上用来建立信任关系的地址的子集。源由规则(scheme)、主机(host)、端口(port)组成,例如由于scheme(https、http)不同,则源不同。
跨源通信通过 源来确定发送者,这就使得接收方可以忽略或者拒绝来自不可信源的消息。同时需要通过添加监听事件来接受消息,以避免被不可信应用程序的信息所干扰。但是在使用外来消息时,即便是可靠的数据源,也同样要谨慎,以防止内容注入。
在使用postMessage API时,需要遵循以下步骤:
1、检查浏览器是否支持
if(typeof window.postMessage === undefined){ //浏览器不支持postMessage }
2、发送消息
window.postMessage("Hello","xx.example.com");
第一个参数包含要发送的数据,第二个参数时消息传递的目的地。
如果要发送消息给iframe,则使用如下代码:
document.getElementById("iframe")[0].contentWindow.postMessage("Hello","xx.example.com");
3、监听消息事件
window.addEventListener("message",messageHandler,true); var originWhiteList = ["a.example.com","b.example.com","c.example.com"]; function messageHandler(e){ if(checkWhiteList(e.origin)){ processMessage(e.data);//发送方实际传送的消息 }else{ //忽略发送的消息 } } function checkWhiteList(origin){ for(var i = 0; i<originWhiteList.length; i++){ if(origin === originWhiteList[i]){ return true; } } return false; }
二、XMLHttpRequestLevel2
XMLHttpRequestLevel2是XMLHttpRequest的改进版本,主要涉及:跨源XMLHttpRequess和进度事件(Progress events)。
XMLHttpRequest仅限于同源通信,XMLHttpRequestLevel2通过跨资源共享实现(Cross Origin Resource Sharing)跨源XMLHttpRequests。
在XMLHttpRequest中通过readystatechange事件来响应进度,但是其在某些浏览器中不被兼容。XMLHttpRequestLevel2用了一个有意义的名字Progress进度来命名进度事件。其进度事件的名称主要有loadstart、progress、abort、error、load、loadend。通过对程序属性设置回调函数,可以实现对这些事件的监听。
在使用XMLHttpRequestLevel2时,需要遵循以下步骤:
1、检查浏览器是否支持
var xhr = new XMLHttpRequest(); if(typeof xhr.withXredentials === undefined){ //浏览器不支持XMLHttpRequest }
2、构建跨源请求
var crossOriginRequest = new XMLHttpRequest(); crossOriginRequest.open("GET","http://www.example.com",true);
在请求过程中,务必确保能够监听到错误,以找出出错原因,解决问题。
3、使用进度事件
crossOriginRequest.onprogress = function(e){ var total = e.total; var loaded = e.loaded; if(e.lengthComputable){ //处理其他事情 } } crossOriginRequest.upload..onprogress = function(e){ var total = e.total; var loaded = e.loaded; if(e.lengthComputable){ //处理其他事情 } }
三、postMessage API示例应用
以跨源聊天应用为例,来演示门户页面和聊天部件之间的交互。
1、创建postMessagePortal.html页面
<!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>跨源通信-WebChat</title> <link rel="stylesheet" href="styles.css"> </head> <h1>跨源通信门户</h1> <p><b>源</b>: http://portal.example.com:8080</p> 状态 <input type="text" id="statusText" value="Online"> <button id="sendButton">更改状态</button> <p> 使用postMessage发送一个状态,以更新包含在此页面中的widgetiframe。 </p> <iframe id="widget" src="http://chat.example.net:8080/communication/postMessageWidget.html"></iframe> <script> var targetOrigin = "http://chat.example.net:8080"; var notificationTimer = null; function messageHandler(e){ if(e.origin == targetOrigin){ notify(e.data); }else{ //忽略 } } function sendString(s){ document.getElementById("widget").contentWindow.postMessage(s,targetOrigin); } function notify(message){ alert(message); } function sendStatus(){ var statusText = document.getElementById("statusText").value; sendString(statusText); } function loadDemo(){ document.getElementById("sendButton").addEventListener("click",sendStatus,true); sendStatus(); } window.addEventListener("load",loadDemo,true); window.addEventListener("message",messageHandler,true); </script>
2、创建postMessageWidget.html
<!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>widget</title> <link rel="stylesheet" href="styles.css"> </head> <h1>Widget iframe</h1> <p><b>源</b>: http://chat.example.net:8080</p> <p>通过门户设置状态为: <strong id="status"></strong> <p> <p> <input type="text" id="messageText" value="Widget notification."> <button id="actionButton">发送通知</button> </p> <script> var targetOrigin = "http://portal.example.com:8080"; window.addEventListener("load",loadDemo,true); window.addEventListener("message",messageHandler,true); function loadDemo(){ document.getElementById("actionButton").addEventListener("click", function() { var messageText = document.getElementById("messageText").value; sendString(messageText); }, true); } function messageHandler(e) { if (e.origin === "http://portal.example.com:8080") { document.getElementById("status").textContent = e.data; } else { // ignore messages from other origins } } function sendString(s) { window.top.postMessage(s, targetOrigin); } </script>
注意:第一、上述的两个页面需要部署到web服务器;第二、两个页面必须来自不同的域。如果要在本机部署,则需要更改hosts文件,增加:
127.0.0.1 portal.example.com 127.0.0.1 chat.example.net
修改完成后,需要关闭浏览器,再次重新打开。
四、XMLHttpRequestLevel2示例应用
1、创建crossOriginUpload.html页面:
<!DOCTYPE html> <head> header(“Access-Control-Allow-Origin: *”); <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>上传地理数据</title> <link rel="stylesheet" href="styles.css"> </head> <script> function loadDemo() { var dataElement = document.getElementById("geodata"); dataElement.textContent = JSON.stringify(geoData).replace(",", ", ", "g"); var xhr = new XMLHttpRequest() if (typeof xhr.withCredentials === undefined) { document.getElementById("support").innerHTML = "浏览器不支持跨源XMLHttpRequest"; } else { document.getElementById("support").innerHTML = "浏览器支持跨源XMLHttpRequest"; } var targetLocation = "http://geodata.example.net:8080/upload"; function setProgress(s) { document.getElementById("progress").innerHTML = s; } document.getElementById("sendButton").addEventListener("click", function() { xhr.upload.onprogress = function(e) { var ratio = e.loaded / e.total; setProgress("已上传" + ratio + "%"); } xhr.onprogress = function(e) { var ratio = e.loaded / e.total; setProgress("已下载" + ratio + "%"); } xhr.onload = function(e) { setProgress("完成"); } xhr.onerror = function(e) { setProgress("错误"); } xhr.open("POST", targetLocation, true); geoDataString = dataElement.textContent; xhr.send(geoDataString); }, true); } window.addEventListener("load", loadDemo, true); </script> <h1>XMLHttpRequest Level 2</h1> <p id="support"></p> <h4>上传地理数据:</h4> <textarea id="geodata"> </textarea> </p> <button id="sendButton">上传</button> <script> geoData = [[39.080018000000003, 39.112557000000002, 39.135261, 39.150458, 39.170653000000001, 39.190128000000001, 39.204510999999997, 39.226759000000001, 39.238483000000002, 39.228154000000004, 39.249400000000001, 39.249533, 39.225276999999998, 39.191253000000003, 39.167993000000003, 39.145685999999998, 39.121620999999998, 39.095761000000003, 39.080593, 39.053131999999998, 39.02619, 39.002929000000002, 38.982886000000001, 38.954034999999998, 38.944926000000002, 38.919960000000003, 38.925261999999996, 38.934922999999998, 38.949373000000001, 38.950133999999998, 38.952649000000001, 38.969692000000002, 38.988512999999998, 39.010652, 39.033088999999997, 39.053493000000003, 39.072752999999999], [-120.15724399999999, -120.15818299999999, -120.15600400000001, -120.14564599999999, -120.141285, -120.10889900000001, -120.09528500000002, -120.077596, -120.045428, -120.0119, -119.98897100000002, -119.95124099999998, -119.93270099999998, -119.927131, -119.92685999999999, -119.92636200000001, -119.92844600000001, -119.911036, -119.942834, -119.94413000000002, -119.94555200000001, -119.95411000000001, -119.941327, -119.94605900000001, -119.97527599999999, -119.99445, -120.028998, -120.066335, -120.07867300000001, -120.089985, -120.112227, -120.09790700000001, -120.10881000000001, -120.116692, -120.117847, -120.11727899999998, -120.14398199999999] ]; </script> <p> <b>状态: </b> <span id="progress">准备</span> </p>
注意:部署web应用,运行crossOriginUpload.html页面时,可能会才出现如下的提示错误:
这是因为访问一页面的域与所请求的域非同源造成的。且浏览器是根据响应头的规则来确定这个域是否同源可以接收。
因此我们需要geodata.example.net:8080/upload在返回内容时,设置Header Access-Control-Allow-Origin,即:
Response.AddHeader("Access-Control-Allow-Origin","*") ;
浏览器在接收到服务器返回信息时,会检查响应头的Access-Control-Allow-Origin,它的值标识请求内容所允许的域。如果将服务器设置Access-Control-Allow-Origin为*,表明该返回信息允许所有源访问。如果设置为具体的域,如xx.com,就表明除了同源外,只允许域来自xx.com的访问。
以上就是HTML5编程之旅-Communication技术初探的内容,更多相关内容请关注PHP中文网(www.php.cn)!

HTML5的核心特性包括语义化标签、多媒体支持、离线存储与本地存储、表单增强。1.语义化标签如、等,提升代码可读性和SEO效果。2.和标签简化多媒体嵌入。3.离线存储和本地存储如ApplicationCache和LocalStorage,支持无网络运行和数据存储。4.表单增强引入新输入类型和验证属性,简化处理和验证。

H5提供了多种新特性和功能,极大地增强了前端开发的能力。1.多媒体支持:通过和元素嵌入媒体,无需插件。2.画布(Canvas):使用元素动态渲染2D图形和动画。3.本地存储:通过localStorage和sessionStorage实现数据持久化存储,提升用户体验。

H5和HTML5是不同的概念:HTML5是HTML的一个版本,包含新元素和API;H5是基于HTML5的移动应用开发框架。HTML5通过浏览器解析和渲染代码,H5应用则需要容器运行并通过JavaScript与原生代码交互。

HTML5的关键元素包括、、、、、等,用于构建现代网页。1.定义头部内容,2.用于导航链接,3.表示独立文章内容,4.组织页面内容,5.展示侧边栏内容,6.定义页脚,这些元素增强了网页的结构和功能性。

HTML5和H5没有区别,H5是HTML5的简称。1.HTML5是HTML的第五个版本,增强了网页的多媒体和交互功能。2.H5常用于指代基于HTML5的移动网页或应用,适用于各种移动设备。

HTML5是超文本标记语言的最新版本,由W3C标准化。HTML5引入了新的语义化标签、多媒体支持和表单增强,提升了网页结构、用户体验和SEO效果。HTML5引入了新的语义化标签,如、、、等,使网页结构更清晰,SEO效果更好。HTML5支持多媒体元素和,无需第三方插件,提升了用户体验和加载速度。HTML5增强了表单功能,引入了新的输入类型如、等,提高了用户体验和表单验证效率。

如何写出干净高效的HTML5代码?答案是通过语义化标签、结构化代码、性能优化和避免常见错误。1.使用语义化标签如、等,提升代码可读性和SEO效果。2.保持代码结构化和可读性,使用适当缩进和注释。3.优化性能,通过减少不必要的标签、使用CDN和压缩代码。4.避免常见错误,如标签未闭合,确保代码有效性。

H5通过多媒体支持、离线存储和性能优化提升网页用户体验。1)多媒体支持:H5的和元素简化开发,提升用户体验。2)离线存储:WebStorage和IndexedDB允许离线使用,提升体验。3)性能优化:WebWorkers和元素优化性能,减少带宽消耗。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

WebStorm Mac版
好用的JavaScript开发工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具