ホームページ > 記事 > ウェブフロントエンド > JavaScript クロスドメインの問題コードの概要
概念: プロトコル、ドメイン名、ポートが異なる限り、それらは異なるドメインとみなされます。
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 不同域名 不允许
ポートとプロトコルの違いは、バックグラウンドでのみ解決できます。
CORS (Cross-Origin Resource Sharing
) クロスドメイン リソース共有は、クロスドメイン リソースにアクセスするときにブラウザとサーバーが通信する方法を定義します。 CORS
の背後にある基本的な考え方は、カスタム HTTP ヘッダーを使用して、ブラウザーがサーバーと通信して、リクエストまたは応答が成功するか失敗するかを判断できるようにすることです。 CORS(Cross-Origin Resource Sharing
)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS
背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。
<script type="text/javascript"> var xhr = new XMLHttpRequest(); xhr.open("GET", "/trigkit4",true); xhr.send(); </script>
以上的trigkit4
是相对路径,如果我们要使用CORS
,相关Ajax
代码可能如下所示:
<script type="text/javascript"> var xhr = new XMLHttpRequest(); xhr.open("GET", "http://segmentfault.com/u/trigkit4/",true); xhr.send(); </script>
代码与之前的区别就在于相对路径换成了其他域的绝对路径,也就是你要跨域访问的接口地址。
服务器端对于CORS
的支持,主要就是通过设置Access-Control-Allow-Origin
来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
要解决跨域的问题,我们可以使用以下几种方法:
现在问题来了?什么是jsonp
?维基百科的定义是:JSONP(JSON with Padding)
是资料格式 JSON
的一种“使用模式”,可以让网页从别的网域要资料。
JSONP
也叫填充式JSON,是应用JSON的一种新方法,只不过是被包含在函数调用中的JSON,例如:
callback({"name","trigkit4"});
JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的JSON数据。
在js中,我们直接用XMLHttpRequest
请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。 例如:
<script type="text/javascript"> function dosomething(jsondata){ //处理获得的json数据 } </script> <script src="http://example.com/data.php?callback=dosomething"></script>
js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。
<?php $callback = $_GET['callback'];//得到回调函数名 $data = array('a','b','c');//要返回的数据 echo $callback.'('.json_encode($data).')';//输出 ?>
最终,输出结果为:dosomething(['a','b','c']);
如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。
<script type="text/javascript"> $.getJSON('http://example.com/data.php?callback=?,function(jsondata)'){ //处理获得的json数据 }); </script>
jquery
会自动生成一个全局函数来替换callback=?
中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON
方法会自动判断是否跨域,不跨域的话,就调用普通的ajax
方法;跨域的话,则会以异步加载js文件的形式来调用jsonp
的回调函数。
JSONP的优点是:它不像XMLHttpRequest
对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript
调用的问题。
CORS与JSONP相比,无疑更为先进、方便和可靠。
1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS)。
浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。
不同的框架之间是可以获取window对象的,但却无法获取相应的属性和方法。比如,有一个页面,它的地址是http://www.php.cn/
, 在这个页面里面有一个iframe
,它的src是http://www.php.cn/
, 很显然,这个页面与它里面的iframe
框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe
<script type="text/javascript"> function test(){ var iframe = document.getElementById('ifame'); var win = document.contentWindow;//可以获取到iframe里的window对象,但该window对象的属性和方法几乎是不可用的 var doc = win.document;//这里获取不到iframe里的document对象 var name = win.name;//这里同样获取不到window对象的name属性 } </script> <iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>上記の
trigkit4
は相対パスです。CORS
を使用する場合、関連する Ajax
コードは次のようになります。 🎜コードと前の違いは、相対パスが他のドメインの絶対パスに置き換えられることです。これは、ドメインを越えてアクセスするインターフェイスのアドレスです。 🎜🎜サーバー側は主に Access-Control-Allow-Origin
を設定することで CORS
をサポートします。ブラウザーが対応する設定を検出すると、Ajax クロスドメイン アクセスを許可できます。 🎜🎜クロスドメインの問題を解決するには、次の方法を使用できます: 🎜🎜 jsonp を介したクロスドメイン🎜🎜 ここで質問が来ますか? jsonp
とは何ですか? Wikipedia の定義は次のとおりです。 JSONP (JSON with Padding)
は、データ形式 JSON
の「使用モード」であり、Web ページが他のドメインからデータをリクエストできるようにします。 🎜🎜JSONP
は、埋め込み JSON とも呼ばれ、JSON を適用する新しい方法です。これは、関数呼び出しに JSON が含まれているだけです。例: 🎜<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe> <script type="text/javascript"> document.domain = 'example.com';//设置成主域 function test(){ alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象 } </script>🎜JSONP は、コールバック関数とデータの 2 つの部分で構成されます。コールバック関数は、応答が来たときにページ内で呼び出される関数であり、データはコールバック関数に渡される JSON データです。 🎜🎜 js では、
XMLHttpRequest
を直接使用して、異なるドメインのデータをリクエストすることはできません。ただし、jsonp はこの機能を使用してページ上に異なるドメインの js スクリプト ファイルを導入することができます。 例: 🎜<script type="text/javascript"> document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同 </script>🎜 js ファイルが正常に読み込まれた後、url パラメーターで指定した関数が実行され、必要な json データがパラメーターとして渡されます。したがって、jsonp はサーバー側ページからの対応する連携を必要とします。 🎜rrreee🎜最終的に、出力結果は次のようになります:
dosomething(['a','b','c']);
🎜🎜 ページで jquery を使用している場合は、そのメソッドを通じてカプセル化できます。 jsonp 操作を実行するのに非常に便利です。 🎜rrreee🎜jquery
は、callback=?
内の疑問符を置き換えるグローバル関数を自動的に生成します。実際には、データは自動的に破棄されます。一時的なプロキシとして機能する関数。 $.getJSON
メソッドは、クロスドメインであるかどうかを自動的に判断し、クロスドメインである場合は通常の ajax
メソッドを呼び出します。 js ファイルを非同期的に呼び出して、jsonp
のコールバック関数を呼び出します。 🎜XMLHttpRequest
オブジェクトによって実装される Ajax リクエストのような同一生成元ポリシーによって制限されないため、互換性が優れています。 , 古いブラウザでも実行でき、XMLHttpRequest や ActiveX のサポートは必要ありません。リクエストの完了後、コールバックを呼び出すことで結果を返すことができます。 🎜🎜JSONP の欠点は、GET リクエストのみをサポートし、POST などの他のタイプの HTTP リクエストはサポートしないこと、クロスドメイン HTTP リクエストのみをサポートし、異なるドメイン の 2 つのページ間で処理を進める方法の問題を解決できないことです。 JavaScript
呼び出しの問題。 🎜🎜CORS と JSONP の比較🎜🎜 JSONP と比較すると、CORS は間違いなくより高度で、便利で、信頼性が高くなります。 🎜🎜1. JSONP は GET リクエストのみを実装できますが、CORS はすべての種類の HTTP リクエストをサポートします。 🎜🎜2. CORS を使用すると、開発者は通常の XMLHttpRequest を使用してリクエストを開始し、データを取得できます。これにより、JSONP よりも優れたエラー処理が可能になります。 🎜🎜3. JSONP は主に古いブラウザーでサポートされており、多くの場合 CORS をサポートしていませんが、最新のブラウザーのほとんどはすでに CORS をサポートしています。 🎜🎜 document.domain を変更してサブドメインを横断する🎜🎜 ブラウザーにはすべて同一生成元ポリシーがあり、その制限の 1 つは、最初の方法で、ajax を使用して異なるソース ドキュメントからファイルをリクエストできないことです。 。 2 番目の制限は、js がブラウザー内の異なるドメインのフレーム間で対話できないことです。 🎜🎜異なるフレームワーク間でウィンドウオブジェクトを取得することは可能ですが、対応するプロパティやメソッドを取得することはできません。たとえば、アドレスが
http://www.php.cn/
であるページがあり、このページには iframe
があり、その src は です。 http://www.php.cn/
では、明らかに、このページとその中の iframe
フレームは異なるドメインにあるため、ページ内に JS コードを記述することはできません。 iframe
: 🎜<script type="text/javascript"> function test(){ var iframe = document.getElementById('ifame'); var win = document.contentWindow;//可以获取到iframe里的window对象,但该window对象的属性和方法几乎是不可用的 var doc = win.document;//这里获取不到iframe里的document对象 var name = win.name;//这里同样获取不到window对象的name属性 } </script> <iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
这个时候,document.domain
就可以派上用场了,我们只要把http://www.php.cn/
和 http://www.php.cn/
这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。
1.在页面 http://www.php.cn/
中设置document.domain
:
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe> <script type="text/javascript"> document.domain = 'example.com';//设置成主域 function test(){ alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象 } </script>
2.在页面 http://www.php.cn/
中也设置document.domain
:
<script type="text/javascript"> document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同 </script>
修改document.domain
的方法只适用于不同子域的框架间的交互。
window
对象有个name
属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name
的,每个页面对window.name
都有读写的权限,window.name
是持久存在一个窗口载入过的所有页面中的
window.postMessage(message,targetOrigin)
方法是html5
新引进的特性,可以使用它来向其它的window
对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera
等浏览器都已经支持window.postMessage
方法。
以上就是JavaScript跨域问题代码总结的内容,更多相关内容请关注PHP中文网(www.php.cn)!