JSONP を紹介する前に、ブラウザの同一生成元ポリシーを紹介しましょう。
同一オリジン ポリシー
同一生成元ポリシーは、Netscape (Netscape) によって提案された有名なセキュリティ ポリシーであり、JavaScript をサポートするすべてのブラウザーがこのポリシーをサポートしています。
いわゆる相同性とは、同じドメイン名、プロトコル、およびポートを指します。 https://it-kiso.com:80/ を例にとると、it-kiso.com はドメイン名、http はプロトコル、80 はポートです (注意: 80 はデフォルトのポートで、省略できます) 、別のポートの場合は、定義を表示する必要があります)。
セキュリティ上の理由から、ブラウザはクロスオリジン リクエストを許可していません。 Web ページとサーバーの間で Ajax を介してデータを送受信する場合、Web ページと要求されたアドレスが同じオリジンであることを確認する必要があります。そうでない場合、要求は成功しません。たとえば、https://it-kiso.com/ の下の Web ページは、https://it-kiso.com/ の下のプログラムとのみ対話できますが、https://www.yahoo.co.jp/ とは対話できません。以下のプログラムが相互作用します。
同一生成元ポリシーにより、JavaScript スクリプトが Web サイトからデータを読み取り、それを他の Web サイトに送信することが防止されます。同一生成元ポリシーがないと、悪意のあるプログラムが Web サイトからコンテンツを漏洩する可能性が高くなります。
同一生成元ポリシーは Web サイトのセキュリティをある程度向上させますが、開発インターフェイスにアクセスするときに、同一生成元ポリシーの存在により呼び出しが失敗するなど、プログラマーにいくつかの問題をもたらします。この問題を解決するには、クロスドメインを使用する必要があります. クロスドメインの方法はたくさんありますが、最も古典的なのは JSONP です.
JSONP とは何ですか?
JSONP の正式名称は「JSON with Padding」で、「JSON with callback」と訳され、JSON の使用モードです。 JSONP を介して、ブラウザーの同一オリジン ポリシーをバイパスし、クロスドメイン リクエストを行うことができます。
Ajaxリクエストを行う場合、same-originポリシーの影響でクロスドメインリクエストができないのですが、 <script>
タグのsrc属性でクロスドメインJavaScriptスクリプトを読み込めるようになっているため、この機能を利用してJSONPを実装しています。通常の Ajax リクエストとは異なり、JSONP がクロスドメイン リクエストに使用される場合、サーバーはデータを JSON 形式で返すのではなく、クロスドメインを実現するために src 属性で呼び出される関数を呼び出す JavaScript コードの一部を返します。 .
JSONP の利点は、互換性が高く、一部の古いブラウザーでも実行できることですが、欠点も非常に明白です。つまり、GET 要求しか作成できません。
JSONP の実装方法
ウェブサイト localhost:8080 から localhost:8081 の下のサーバーにリクエストを送信するとします。サーバーは次のコンテンツを返します。
{“name”:”IT Foundation”, “url”:”https://it-kiso.com/”}
Ajax リクエストを直接送信すると、同一オリジン ポリシーにより、ウェブサイトとサーバーのオリジンが異なるため、リクエストはブロックされます。サンプルコードは次のとおりです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
<div id="result"></div>
<button type="button" onclick="sendAjax()">送信</button>
<script>
function sendAjax() {
// XMLHttpRequestオブジェクトの作成
var request = new XMLHttpRequest();
// リクエストオブジェクトのインスタンス化
request.open("GET", "http://localhost:8081/test.php");
// readyStateの変化を監視
request.onreadystatechange = function() {
// リクエストが成功したかどうかを確認
if(this.readyState === 4 && this.status === 200) {
// サーバーからの応答を現在のページに挿入
document.getElementById("result").innerHTML = this.responseText;
}
};
// サーバーにリクエストを送信
request.send();
}
</script>
</body>
</html>
ページの [リクエストを送信] ボタンをクリックすると、次のエラーが返されます。
‘http://localhost:8081/test.php’ でオリジン ‘http://localhost:8080’ からの XMLHttpRequest へのアクセスが CORS ポリシーによってブロックされました: ‘Access-Control-Allow-Origin’ ヘッダーが要求されたリソース。
http://localhost:8081/test.php net::ERR_FAILED を取得します
サーバーからデータを正常に取得したい場合は、上記で紹介した JSONP を使用して実現できます。実装手順は次のとおりです。
次のように、 <script>
タグを使用して、タグの src 属性を要求するアドレスに設定します。
<script src=”http://localhost:8081/test.php”></script>
この時点で、 <script>
タグが返されたコンテンツを自動的に解析して実行することがわかります.コンテンツが完全な JavaScript コードでない場合、プログラムはエラーを報告します.したがって、JSONP クロスドメイン リクエストを行う場合、サーバーが完全な JavaScript コードを返すようにする必要があります。
さらに、JSON データは自動的に JavaScript オブジェクトに変換されるため、返されるコンテンツを純粋な JSON データにすることはできませんが、変数に代入したり、関数に渡したりしないと使用できません。
そのため、リクエストにコールバック関数(パラメータとして渡される関数。一般的な関数と同等)を提供し、この関数をサーバー経由で返し、返されるJSONデータを<script>
タグ この関数は、返されたコンテンツが解析および実行されるときに自動的に呼び出されます。サンプルコードは次のとおりです。
<script src=”http://localhost:8081/test.php?callback=showJsonData”></script>
サーバー http://localhost:8081/ の完全なコードは次のとおりです。
'IT基礎', 'url'=>'https://it-kiso.com/'); // 戻り値として返す内容を含む配列を定義
$callback = $_GET['callback']; // コールバック関数をリクエストから受信
echo $callback."(".json_encode($data).")"; // 上記の配列をJSON形式に変換し、関数に引数として連結してフロントエンドに返す
return; // 以降の処理を停止する
?>
Web サイト localhost:8080 の完全なコードは次のとおりです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
<script>
function showJsonData(data){
console.log(data);
}
</script>
<script src="http://localhost:8081/test.php?callback=showJsonData"></script>
</body>
</html>
操作の結果は次のとおりです。
{name: ‘IT Foundation’, url: ‘https://it-kiso.com/’}
JSONP を使用すると、ブラウザーの同一オリジン ポリシーを回避し、クロスドメイン リクエストを行うことができます。 JSONP は、HTML タグの src 属性を使用して、同一生成元ポリシーの影響を受けないリソースを参照することによって実装されます。実装手順は次のとおりです。
- 要求アドレスにコールバック関数をスプライスして新しいアドレスを取得し、この新しいアドレスを <script> タグの src 属性に割り当てます。
- サーバーはこのコールバック関数を受け取り、パラメーターを関数に挿入してから、関数とそのパラメーターを文字列の形式で返します。
- <script> 返されたコンテンツを受け取ると、そのコンテンツを JavaScript コードの一部として扱い、自動的に実行します。
注: サーバーから返されるコンテンツは、他のコンテンツではなく、実行可能な JavaScript コードである必要があります。