LoginSignup
2
0

More than 1 year has passed since last update.

window.openを使って、URL非表示で開く(制約あり)

Last updated at Posted at 2023-03-22

友達に言われて、こんな感じの実装もありじゃね?という感じのノリで書いている記事です。

制約

この実装を使う場合、以下の制約を守らないと上手く動かないと思います。

  • 開くページに遷移がないこと(リンクを踏んで別のページに移動しないこと)
  • 開くページが同じドメイン内であるか、クロスオリジンOKなこと
  • 同じHTTPS/HTTPプロトコルで通信していること

実装

URL非表示のページを開くテスト

<button id='btn'>開く</button>

<script>
// 開くボタンが押されたら
document.getElementById('btn').onclick = () => {
  fetch('/supersecret.html', {method: 'GET'})
    .then(data => data.text())
    .then(res => {

        // ウィンドウを作成する
        let w = window.open('','_blank', 'popup=1');

        // 初期状態としてHTMLを直接挿入
        w.document.body.innerHTML = res


        // ページがリロードされた時のハンドラー
        const resetHandler = () => {
          w.addEventListener('beforeunload', () => {

            // もしリロードされたら、0.1秒待ってHTMLを挿入しハンドラーをリセットする
            setTimeout(() => {
              try{
                w.document.body.innerHTML = res;
              } catch(err){
                // クロスオリジンでエラー(URLバーが直接編集されたような場合)は、windowを閉じる
                w.close();
              }
              resetHandler();
            }, 100);
            
          });
        }

        resetHandler();
    })
}

</script>

デモ:https://165cmtallboy.github.io/secret-window/

解説

fetchで生のHTMLを直接取得し、そのデータをwindow.body.innerHTMLを通して直接ウィンドウに書き込んでいます。
ページ自体を読み込ませているさせているわけではないので、ブラウザ上のURLバーにはURLが表示されません。

image.png

サンプルコード

そのままWebサーバに置けば動きます

注意

ウェブ触ったことある人なら瞬殺でURL取られると思います。
絶対に他の人にURLを渡されたくない、ワンタイムなページを提供したい場合は
リンクに識別のためのパラメータをつけておいて、一度使われたパラメータには2度と見せないとかサーバー側の実装をしないと行けないと思います。

GET: /secretpage?token=929829503201

一度アクセスがあったトークン(929829503201)には403 Forbiddenを返す。みたいな
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0