1. ホーム
  2. Web制作
  3. html5

html5 postMessageのフロントエンドクロスドメインとフロントエンドのリスニング方式の例

2022-02-01 01:30:13

時には、フロントエンドでシングルサインオンをしろ!などという馬鹿げた要求もあります。要件を受けたら、解決策を考えなければなりません。

ここで、簡単なフロントエンドのシングルサインオンソリューションを作ってみましょう。

postMessageのクロスドメインメッセージングとonstorageのリスニングを使用しています。

この記事で使用した知識: KOA 静的リソースサービスの設定、クロスドメイン、postMessage の使用法、onstorage のストレージへのリスニング

最初のステップは、2つの異なるポートでサービスをセットアップすることです。

ここではkoa2を使って、実際の業務で発生する必要のあるクロスドメインの状況をシミュレートするために、異なるポートに2つのサービスを構築しています。

とてもシンプルですね。主にkoa-staticというミドルウェアを使っています。
もしあなたがノード関連の知識を学びたいなら、私のWeChat shouzi_1994を追加するか、ブログの下にあなたの連絡先を残してください。

// localhost:4000
const Koa = require('koa');
const path = require('path')
const static = require('koa-static')
const app = new Koa();

// Set the path to the static resource 
const staticPath = '. /static'

app.use(static(
    path.join( __dirname, staticPath)
  ))

  
console.log("Service started on port 4000")

app.listen(4000);


// localhost:3000
const Koa = require('koa');
const path = require('path')
const static = require('koa-static')
const app = new Koa();

// Set the path to the static resource 
const staticPath = '. /static'

app.use(static(
    path.join( __dirname, staticPath)
  ))


console.log("Service started on port 4000")

app.listen(4000);

ステップ2、クロスドメインコミュニケーション postMessage

まず、postMessageのAPIを見てみましょう。

otherWindow.postMessage(message, targetOrigin, [transfer]);

他のウィンドウ
iframe の contentWindow プロパティ、window.open の実行により返されるウィンドウ オブジェクト、名前付きまたは数値インデックス付きの window.frames などの、別のウィンドウへの参照です。

メッセージ
他のウィンドウに送信するデータです。構造化クローンアルゴリズムによってシリアライズされる。つまり、データオブジェクトを自分でシリアライズすることなく、何の制限もなく安全にターゲットウィンドウに送信することができます。[1]

ターゲットオリジン
その値は文字列 "" (無制限の場合) または URI のいずれかです。メッセージを送信するとき、ターゲットウィンドウのプロトコル、ホストアドレス、ポートの 3 つのうち 1 つでも targetOrigin で指定した値に一致しない場合、メッセージは送信されません。3つすべてが正確に一致した場合のみ、メッセージは送信される。例えば、postMessage でパスワードを送信する場合、悪意のある第三者に傍受されないように、このパラメータの値が、パスワードを含むメッセージの受信予定者の origin 属性と正確に一致することが特に重要なのです。もしどのウィンドウにメッセージを送るべきか正確に知っているのであれば、代わりに必ず正確な値を targetOrigin に指定してください。正確なターゲットを指定しないと、そのデータに興味を持つ悪意のあるサイトにデータが漏えいすることになります。

転送 オプション
は、メッセージとともに渡される転送可能なオブジェクトの文字列です。これらのオブジェクトの所有権はメッセージの受信者に移り、送信者は所有権を保持しなくなる。

どうです、わかりやすいでしょう!ここでちょっとだけ文化を紹介しましょう。

転送先の(親)子ウィンドウ。postMessage(何を転送するか、どのアドレスに転送するか、[パーミッションを転送するかどうか(通常は使用しません)])。

あらかじめ、ドメインをまたいで転送するためには、親子ページ、つまりjsで開くページ、ifreamでネストされたページであることが必要です

では、コードを書き始めましょう

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
        <! -- postMessage and iframe solve common cross-domain problems -->
    I am the content of the port 3000 site
    <button onclick="send()">Send message to son</button>
    
    <iframe style="display:none" src="http://localhost:4000" frameborder="0"></iframe>
<script>
        function send() { 
                window.frames[0].postMessage({a:"1"},"http://localhost:4000"); // trigger the message-event for the cross-domain subpage
        }

    window.addEventListener('message', function(event) {
        console.info('A letter from my son', event);
    }, false);
</script>
</body>
</html>


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
        <! -- postMessage and iframe solve common cross-domain problems -->
    I am the content of the port 4000 site
    <button onclick="send()">Send message to dad</button>
    
    <iframe style="display:none" src="http://localhost:4000" frameborder="0"></iframe>
<script>
       window.addEventListener("message",function(event){
           console.log("A letter from dad: ", event)
        },false)

      function send() {
        parent.postMessage({a:1}, 'http://localhost:3000'); // 
     }
</script>
</body>
</html>

この時点で、親ページと子ページの間のクロスドメイン通信を実装しましたが、この通信はウィンドウ内でしか行われず、私が望むような効果は得られないので、どうすればよいでしょうか。

値の変化をリスニングし、時間内に反応する

この時点までに、同じドメインのすべてのサイトが、ブラウザ上で何が見えるかを考える必要があります。

そうだ、ストレージだ!これを聞けばいいんだ。

ここでは、loacalStorageをリッスンすることを選択します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
        <! -- postMessage and iframe solve common cross-domain problems -->
    I am the content of the port 4000 site
    <button onclick="send()">Send message to dad</button>
    
    <iframe style="display:none" src="http://localhost:4000" frameborder="0"></iframe>
<script>
    
       window.addEventListener("message",function(event){
           console.log("A letter from Dad: ", event)
           var data = JSON.stringify(event.data)
           window.localStorage.setItem("data",data)
        },false)

        window.onstorage(function(st){
            console.log(st.key,st.value)
        })
      function send() {
        parent.postMessage({a:1}, 'http://localhost:3000'); // 
     }

</script>

</body>
</html>

ほら、もうクロスドメイン転送に対応できるようになったでしょ?

について考える

2ページ分のクロスドメインコミュニケーションができたので、3ページから多数へのクロスドメインコミュニケーションはどうすればいいのでしょうか?それは、理にかなっています。根拠を示したので、実際に書いて体験してみてください。

この記事がお役に立てれば幸いです。そして、スクリプトハウスを応援していただければと思います。