目次
なぜ同一生成元制限があるのですか? " >なぜ同一生成元制限があるのですか?
ホームページ ウェブフロントエンド フロントエンドQ&A JavaScriptの同一生成元ポリシーとは何ですか

JavaScriptの同一生成元ポリシーとは何ですか

Jan 26, 2022 pm 02:14 PM
javascript 同一生成元ポリシー

JavaScript では、同一オリジン ポリシーは、クライアント側スクリプト (特に Javascript) にとって重要なセキュリティ メトリックです。つまり、同じプロトコル (プロトコル)、ポート、ホスト (ドメイン名) を持つ 2 つのページです。同じソースに属します。

JavaScriptの同一生成元ポリシーとは何ですか

このチュートリアルの動作環境: Windows7 システム、JavaScript バージョン 1.8.5、Dell G3 コンピューター。

同一生成元ポリシーとは何ですか?

同一生成元ポリシーは、クライアント側スクリプト (特に Javascript) の重要なセキュリティ メトリックです。これは Netscape Navigator 2.0 で最初に登場したもので、その目的はドキュメントやスクリプトが複数の異なるソースからロードされるのを防ぐことでした。

同一オリジン ポリシーとは、同じプロトコル、ポート (指定されている場合)、およびホスト (ドメイン名) を持つ 2 つのページが同じソースに属することを意味します。

例: http://www.example.com/dir/page.htmlこの URL、
プロトコルは http://、
ドメイン名は www .example.com,
ポートは 80 です (デフォルトのポートは省略可能)。その相同性は以下の通りである。

    http://www.example.com/dir2/other.html:同源
    http://example.com/dir/other.html:不同源(域名不同)
    http://v2.www.example.com/dir/other.html:不同源(域名不同)
    http://www.example.com:81/dir/other.html:不同源(端口不同)
ログイン後にコピー

本質:

本質は単純です。あらゆるサイトから読み込まれた信頼できるコンテンツは安全ではないとみなします。ブラウザーによって信頼されていないスクリプトがサンドボックスで実行される場合、悪意のある可能性のある他のサイトからのリソースではなく、同じサイトからのリソースへのアクセスのみを許可する必要があります。

なぜ同一生成元制限があるのですか?

例を挙げてみましょう: たとえば、ハッカー プログラムは IFrame を使用して、実際の銀行ログイン ページをページに埋め込みます。実際のユーザー名とパスワードでログインすると、彼のページには次の内容が表示されます。フォームへの入力は Javascript を通じて読み取ることができるため、ユーザー名とパスワードを簡単に取得できます。

同一生成元ポリシーの目的は、ユーザー情報のセキュリティを確保し、悪意のある Web サイトによるデータの盗難を防ぐことです。

次のような状況を想像してください: Web サイト A は銀行であり、ユーザーはログインした後、他の Web サイトを閲覧します。他の Web サイトが Web サイト A の Cookie を読み取ることができたらどうなりますか?

明らかに、Cookie にプライバシー (入金額の合計など) が含まれている場合、その情報は漏洩します。さらに恐ろしいのは、ユーザーのログイン状態を保存するために Cookie がよく使用されており、ユーザーがログアウトしないと、他の Web サイトがユーザーになりすまして、やりたいことが何でもできるようになるということです。ブラウザーは、フォームの送信が同一生成元ポリシーによって制限されないことも規定しているためです。

「同一生成元ポリシー」が必要であることがわかります。そうしないと、Cookie が共有される可能性があり、インターネットはまったく安全ではなくなります。

制限範囲

インターネットの発展に伴い、「同一生成元ポリシー」はますます厳しくなっています。現在、同じ起源でない場合に制限される動作が 3 つあります。

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) Ajax 请求不能发送。
ログイン後にコピー

これらの制限は必要ですが、場合によっては不便であり、合理的な目的に影響を与えます。以下では、上記 3 つの制限を回避する方法を詳しく紹介します。

#回避方法

1. Cookie

#Cookie は、次の方法で書き込まれる情報です。サーバーからブラウザへ小さな情報は、同じオリジンを持つ Web ページ間でのみ共有できます。ただし、2 つの Web ページの第 1 レベルのドメイン名は同じですが、第 2 レベルのドメイン名は異なります。ブラウザでは、

document.domain を設定することで Cookie を共有できます。

たとえば、Web ページ A は

http://w1.example.com/a.html、Web ページ B は http://w2.example.com/ b .html の場合、同じ document.domain が設定されている限り、2 つの Web ページは Cookie を共有できます。

document.domain = 'example.com';
ログイン後にコピー

これで、Web ページ A はスクリプトを通じて Cookie を設定します。

document.cookie = "test1=hello";
ログイン後にコピー

Web ページ B はこの Cookie を読み取ることができます。

var allCookie = document.cookie;
ログイン後にコピー

このメソッドは Cookie および iframe ウィンドウにのみ適用できます。LocalStorage および IndexDB ではこのメソッドを使用できません。

同一生成元ポリシーを回避するには、以下で紹介する PostMessage API を使用する必要があります。

さらに、サーバーは、Cookie を設定するときに .example.com など、Cookie のドメイン名を第 1 レベルのドメイン名として指定することもできます。

 Set-Cookie: key=value; domain=.example.com; path=/
ログイン後にコピー

この場合、第 2 レベル ドメイン名と第 3 レベル ドメイン名の両方が設定なしでこの Cookie を読み取ることができます。

2. iframe

2 つの Web ページのソースが異なる場合、相手の DOM を取得できません。典型的な例は、iframe ウィンドウと、親ウィンドウと通信できない window.open メソッドによって開かれたウィンドウです。

たとえば、親ウィンドウが次のコマンドを実行する場合、iframe ウィンドウが同じオリジンのものでない場合、エラーが報告されます。

document.getElementById("myIFrame").contentWindow.document
 // Uncaught DOMException: Blocked a frame from accessing a cross-origin frame.
ログイン後にコピー

上記のコマンドでは、親ウィンドウは次のコマンドを実行します。子ウィンドウの DOM を取得すると、クロスオリジンのためエラーが報告されます。

逆に、子ウィンドウもメイン ウィンドウの DOM を取得するときにエラーを報告します。

 window.parent.document.body    // 报错
ログイン後にコピー

2 つのウィンドウの第 1 レベルのドメイン名が同じであるが、第 2 レベルのドメイン名が異なる場合は、前のセクションで紹介した

document.domain 属性を設定します。同一生成元ポリシーを回避して DOM を取得できます。

まったく異なる起源を持つ Web サイトの場合、クロスドメイン ウィンドウの通信の問題を解決する方法は現在 3 つあります。

    フラグメント識別子
  • window.name
  • クロスドキュメント メッセージング API

2.1 フラグメント識別子

片段标识符(fragment identifier)指的是,URL的#号后面的部分,比如http://example.com/x.html#fragment的#fragment。如果只是改变片段标识符,页面不会重新刷新。

父窗口可以把信息写入子窗口的片段标识符。

var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;
ログイン後にコピー

子窗口通过监听hashchange事件得到通知。

window.onhashchange = checkMessage;

    function checkMessage() {
      var message = window.location.hash;
      // ...
    }
ログイン後にコピー

同样的,子窗口也可以改变父窗口的片段标识符。

 parent.location.href= target + "#" + hash;
ログイン後にコピー

2.2 window.name

浏览器窗口有window.name属性。这个属性的最大特点是,无论是否同源,只要在同一个窗口里,前一个网页设置了这个属性,后一个网页可以读取它。

父窗口先打开一个子窗口,载入一个不同源的网页,该网页将信息写入window.name属性。

window.name = data;
ログイン後にコピー

接着,子窗口跳回一个与主窗口同域的网址。

location = 'http://parent.url.com/xxx.html';
ログイン後にコピー

然后,主窗口就可以读取子窗口的window.name了。

var data = document.getElementById('myFrame').contentWindow.name;
ログイン後にコピー

这种方法的优点是,window.name容量很大,可以放置非常长的字符串;缺点是必须监听子窗口window.name属性的变化,影响网页性能。

2.3 window.postMessage

上面两种方法都属于破解,HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。

这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。

举例来说,父窗口http://aaa.com向子窗口http://bbb.com发消息,调用postMessage方法就可以了。

 var popup = window.open('http://bbb.com', 'title');
 popup.postMessage('Hello World!', 'http://bbb.com');
ログイン後にコピー

postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即”协议 + 域名 + 端口”。也可以设为*,表示不限制域名,向所有窗口发送。

子窗口向父窗口发送消息的写法类似。

window.opener.postMessage('Nice to see you', 'http://aaa.com');
ログイン後にコピー

父窗口和子窗口都可以通过message事件,监听对方的消息。

window.addEventListener('message', function(e) {
  console.log(e.data);
},false);
ログイン後にコピー

message事件的事件对象event,提供以下三个属性。

    event.source:发送消息的窗口
    event.origin: 消息发向的网址
    event.data: 消息内容
ログイン後にコピー

下面的例子是,子窗口通过event.source属性引用父窗口,然后发送消息。

    window.addEventListener('message', receiveMessage);
    function receiveMessage(event) { 
       event.source.postMessage('Nice to see you!', '*');
    }
ログイン後にコピー

event.origin属性可以过滤不是发给本窗口的消息。

window.addEventListener('message', receiveMessage);
 function receiveMessage(event) {
   if (event.origin !== 'http://aaa.com') return;
   if (event.data === 'Hello World') {
       event.source.postMessage('Hello', event.origin);
   } else {
     console.log(event.data);
   }
 }
ログイン後にコピー

2.4 LocalStorage

通过window.postMessage,读写其他窗口的 LocalStorage 也成为了可能。

下面是一个例子,主窗口写入iframe子窗口的localStorage。

window.onmessage = function(e) {
   if (e.origin !== 'http://bbb.com') {
        return;
   }   
   var payload = JSON.parse(e.data);
   localStorage.setItem(payload.key, JSON.stringify(payload.data));
 };
ログイン後にコピー

上面代码中,子窗口将父窗口发来的消息,写入自己的LocalStorage。

父窗口发送消息的代码如下。

var win = document.getElementsByTagName('iframe')[0].contentWindow;
var obj = { name: 'Jack' };
win.postMessage(JSON.stringify({key: 'storage', data: obj}), 'http://bbb.com');
ログイン後にコピー

加强版的子窗口接收消息的代码如下。

window.onmessage = function(e) {
 if (e.origin !== 'http://bbb.com') return;
 var payload = JSON.parse(e.data);
 switch (payload.method) {
   case 'set':
     localStorage.setItem(payload.key, JSON.stringify(payload.data));
     break;
   case 'get':
     var parent = window.parent;
     var data = localStorage.getItem(payload.key);
     parent.postMessage(data, 'http://aaa.com');
     break;
   case 'remove':
     localStorage.removeItem(payload.key);
     break;
 }
};
ログイン後にコピー

加强版的父窗口发送消息代码如下。

var win = document.getElementsByTagName('iframe')[0].contentWindow;
 var obj = { name: 'Jack' };
 // 存入对象
 win.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://bbb.com');
 // 读取对象
 win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
 window.onmessage = function(e) {
   if (e.origin != 'http://aaa.com') return;
   // "Jack"
   console.log(JSON.parse(e.data).name);
 };
ログイン後にコピー

3、Ajax

同源政策规定,AJAX请求只能发给同源的网址,否则就报错。

除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制。

    JSONP
    WebSocket
    CORS
ログイン後にコピー

3.1 JSONP

JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。

它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

首先,网页动态插入<script>元素,由它向跨源网址发出请求。

   function addScriptTag(src) {
      var script = document.createElement(&#39;script&#39;);
      script.setAttribute("type","text/javascript");
      script.src = src;
      document.body.appendChild(script);
    }

    window.onload = function () {
      addScriptTag(&#39;http://example.com/ip?callback=foo&#39;);
    }    function foo(data) {
      console.log(&#39;Your public IP address is: &#39; + data.ip);
    };
ログイン後にコピー

上面代码通过动态添加<script>元素,向服务器example.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于JSONP是必需的。

服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。

foo({
  "ip": "8.8.8.8"
});
ログイン後にコピー

由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因此避免了使用JSON.parse的步骤。

3.2 WebSocket

WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

下面是一个例子,浏览器发出的WebSocket请求的头信息(摘自维基百科)。

    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
    Sec-WebSocket-Protocol: chat, superchat
    Sec-WebSocket-Version: 13
    Origin: http://example.com
ログイン後にコピー

上面代码中,有一个字段是Origin,表示该请求的请求源(origin),即发自哪个域名。

正是因为有了Origin这个字段,所以WebSocket才没有实行同源政策。因为服务器可以根据这个字段,判断是否许可本次通信。如果该域名在白名单内,服务器就会做出如下回应。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
ログイン後にコピー

3.3 CORS

CORS は Cross-Origin Resource Sharing の略称です。これは W3C 標準であり、クロスオリジン AJAX リクエストの基本的なソリューションです。 GET リクエストのみを送信できる JSONP と比較して、CORS ではあらゆる種類のリクエストが許可されます。

[関連する推奨事項: JavaScript 学習チュートリアル]

以上がJavaScriptの同一生成元ポリシーとは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 Dec 17, 2023 pm 02:54 PM

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 Dec 17, 2023 pm 12:09 PM

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 Dec 17, 2023 am 09:39 AM

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

JavaScriptでinsertBeforeを使用する方法 JavaScriptでinsertBeforeを使用する方法 Nov 24, 2023 am 11:56 AM

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。

JavaScript で HTTP ステータス コードを簡単に取得する方法 JavaScript で HTTP ステータス コードを簡単に取得する方法 Jan 05, 2024 pm 01:37 PM

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

See all articles