【HTML】常用跨域技术

来源:互联网 发布:java代码换行符 编辑:程序博客网 时间:2024/06/06 05:29

    • 什么是跨域
    • XmlHttpResponse
    • 图像Pingiframe
    • JSONP
    • WebSocket


什么是跨域

出于安全方面的考虑,运行在同一浏览器中的框架,标签页,窗口间的通信一直都受到了严格的限制。而现实中存在将不同站点的内同在浏览器上进行交互的需求,这就需要使用**跨域**.

网上列的这个表不错,一目了然:

URL 说明 是否允许通信 http://www.a.com/a.js http://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.js http://www.a.com/script/b.js 同一域名下不同文件夹 允许 http://www.a.com:8000/a.js http://www.a.com/b.js 同一域名,不同端口 不允许 http://www.a.com/a.js https://www.a.com/b.js 同一域名,不同协议 不允许 http://www.a.com/a.js http://70.32.92.74/b.js 域名和域名对应ip 不允许 http://www.a.com/a.js http://script.a.com/b.js 主域相同,子域不同 不允许 http://www.a.com/a.js http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问) http://www.cnblogs.com/a.js http://www.a.com/b.js 不同域名 不允许

注意一下实例需要在server上运行。
常见的几种server都能使用

  • Tomcat 网址输入:localhost:8080/*.html
  • Apache 网址输入:localhost:80/*.html
  • 安装有Python的话,CMD/PowerShell在文件目录下输入python -m SimpleHTTPServer 9999,网址输入:localhost:9999/*.html

CORS(Cross-Origin Resource Sharing,跨源资源共享)

1.XmlHttpResponse

Firefox 3.5+、Safari 4+、Chrome、iOS 版Safari 和Android 平台中的WebKit 都通过XMLHttpRequest对象实现了对CORS 的原生支持。在尝试打开不同来源的资源时,无需额外编写代码就可以触发这个行为。要请求位于另一个域中的资源,使用标准的XHR 对象并在open()方法中传入绝对URL 即可

<!DOCTYPE html><html><head>    <title>Cross-Browser CORS Request Example</title></head><body>    <p>This example must be run on a server to work properly and will only work in browsers supporting CORS.</p>    <script>        function createCORSRequest(method, url){            var xhr = new XMLHttpRequest();            if ("withCredentials" in xhr){                xhr.open(method, url, true);            } else if (typeof XDomainRequest != "undefined"){//=====IE                xhr = new XDomainRequest();                xhr.open(method, url);            } else {                xhr = null;            }            return xhr;        }        var request = createCORSRequest("get", "http://www.somewhere-else.com/xdr.php");        if (request){            request.onload = function(){                //do something with request.responseText            };            request.send();        }    </script></body></html>

注:与 IE 中的XDR 对象不同,通过跨域XHR 对象可以访问status 和statusText 属性,而且还支持同步请求。
 不能使用 setRequestHeader()设置自定义头部。
 不能发送和接收cookie。
 调用 getAllResponseHeaders()方法总会返回空字符串。


补充:
CORS 通过一种叫做Preflighted Requests 的透明服务器验证机制支持开发人员使用自定义的头部、GET 或POST 之外的方法,以及不同类型的主体内容。
1.1 预请求(Preflighted Reqeusts)

var invocation = new XMLHttpRequest();var url = 'http://bar.other/resources/post-here/';var body = '{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}Arun';function callOtherDomain(){  if(invocation)    {      invocation.open('POST', url, true);      invocation.setRequestHeader('X-PINGOTHER', 'pingpong');//自定义请求头      invocation.setRequestHeader('Content-Type', 'application/xml');      invocation.onreadystatechange = handler;      invocation.send(body);     }......

如上,以 XMLHttpRequest 创建了一个 POST 请求,为该请求添加了一个自定义请求头(X-PINGOTHER: pingpong),并指定数据类型为 application/xml。所以,该请求是一个“预请求”形式的跨站请求。
1.2 带凭据的请求
默认情况下,跨源请求不提供凭据(cookie、HTTP 认证及客户端SSL 证明等)。通过将withCredentials 属性设置为true,可以指定某个请求应该发送凭据。如果服务器接受带凭据的请求,会用下面的HTTP 头部来响应。

var invocation = new XMLHttpRequest();var url = 'http://bar.other/resources/credentialed-content/';function callOtherDomain(){  if(invocation) {    invocation.open('GET', url, true);    invocation.withCredentials = true;//使得Cookies可以随着请求发送    invocation.onreadystatechange = handler;    invocation.send();   }

客户端与浏览器端的交互如下:

GET /resources/access-control-with-credentials/ HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3preAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7Connection: keep-aliveReferer: http://foo.example/examples/credential.htmlOrigin: http://foo.exampleCookie: pageAccess=2HTTP/1.1 200 OKDate: Mon, 01 Dec 2008 01:34:52 GMTServer: Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2X-Powered-By: PHP/5.2.6Access-Control-Allow-Origin: http://foo.exampleAccess-Control-Allow-Credentials: trueCache-Control: no-cachePragma: no-cacheSet-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMTVary: Accept-Encoding, OriginContent-Encoding: gzipContent-Length: 106Keep-Alive: timeout=2, max=100Connection: Keep-AliveContent-Type: text/plain

Cookie: pageAccess=2,可以看到有Cookie了。
Access-Control-Allow-Origin: http://foo.example不能为*,否者错误。

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

2.图像Ping/iframe

 <script>        var img = new Image();        img.onload = img.onerror = function(){            alert("Done!");        };        img.src = "http://www.example.com/test?name=Nicholas";     </script>

iframe也是用src属性

3.JSONP

<script>           function handleResponse(response){            alert("You're at IP address " + response.ip + ", which is in " + response.city + ", " + response.region_name);        }          var script = document.createElement("script");        script.src = "http://freegeoip.net/json/?callback=handleResponse";        document.body.insertBefore(script, document.body.firstChild);    </script>

这里写图片描述
控制台NetWork
这里写图片描述

4.WebSocket

由于 Web Sockets 使用了自定义的协议,所以URL 模式也略有不同。未加密的连接不再是http://,而是ws://;加密的连接也不是https://,而是wss://。在使用Web Socket URL 时,必须带着这个模式,因为将来还有可能支持其他模式。
这里我们举一个《HTML5 高级程序设计》书中的例子:
- 使用Python服务器 python -m SimpleHTTPServer 9999。
- 其中websocket服务器在文件夹中websocket.py 通过命令:python websocket.py开启
代码:

<!DOCTYPE html><title>WebSocket Test Page</title><script>    var log = function(s) {        if (document.readyState !== "complete") {            log.buffer.push(s);        } else {            document.getElementById("output").innerHTML += (s + "\n")        }    }    log.buffer = [];     url = "ws://localhost:8080/echo";     w = new WebSocket(url);    w.onopen = function() {        log("open");        w.send("thank you for accepting this Web Socket request");    }    w.onmessage = function(e) {        log(e.data);    }    w.onclose = function(e) {        log("closed");    }    window.onload = function() {        log(log.buffer.join("\n"));        document.getElementById("sendButton").onclick = function() {            w.send(document.getElementById("inputMessage").value);        }    }</script><input type="text" id="inputMessage" value="Hello, Web Socket!"><button id="sendButton">Send</button><pre id="output"></pre>

网址输入:http://localhost:9999/websocket.html

另外还有一些可以参考其他博客:

JavaScript跨域总结与解决办法:
http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html

0 0
原创粉丝点击