クリップボードのセキュリティ制限は「ユーザーを守るための強いガード」
クリップボードには、ユーザーがコピーしたあらゆる情報が入ります。
パスワード、クレカ番号、住所、仕事の文章、社外秘のコード——全部です。
もし Web ページが、ユーザーの知らないところで
- 勝手にクリップボードを読み取れる
- 勝手にクリップボードを書き換えられる
としたら、それだけでかなり危険ですよね。
だからブラウザは、Clipboard API に対して
かなり強めの「セキュリティ制限」をかけています。
ここをちゃんと理解しておくと、
「なんで動かないの?」ではなく
「これはブラウザがユーザーを守っているんだな」
と、挙動に納得できるようになります。
大前提:Clipboard API は「安全なコンテキスト」でしか基本的に動かない
HTTPS じゃないと、そもそも門前払いされることが多い
Clipboard API(navigator.clipboard.*)は、
ほとんどのブラウザで「安全なコンテキスト」でしか使えません。
安全なコンテキストとは、ざっくり言うと
https://で始まるページ- もしくは
http://localhost(ローカル開発用の特別扱い)
です。
例えば、こんなコードを書いたとします。
async function copyText() {
await navigator.clipboard.writeText("hello");
}
JavaScriptこれを http://example.com みたいな
「ただの HTTP ページ」で動かそうとすると、navigator.clipboard 自体が undefined だったり、
呼び出し時にエラーになったりします。
「なんで?」の答えはシンプルで、
「安全じゃない通信のページに、
OS のクリップボードを触らせたくない」
からです。
開発者としては、
- 本番は必ず HTTPS
- ローカル開発は
http://localhost
という前提で考えるのが基本になります。
もうひとつの大前提:ユーザー操作に紐づいていないとほぼ拒否される
「勝手に」コピー・ペーストはさせてもらえない
Clipboard API の呼び出しは、
基本的に「ユーザー操作に紐づいている必要」があります。
例えば、次のようなコードはほぼアウトです。
// ページ読み込み直後に勝手にコピーしようとする
window.addEventListener("load", async () => {
await navigator.clipboard.writeText("勝手にコピー");
});
JavaScriptブラウザからすると、
「ユーザーは何もしていないのに、
このページがいきなりクリップボードをいじろうとしている」
という状態なので、当然拒否します。
一方で、次のようなコードは「許されやすい」です。
button.addEventListener("click", async () => {
await navigator.clipboard.writeText("ユーザーがボタンを押したのでコピー");
});
JavaScriptここでは、
- ユーザーがボタンをクリック
- そのイベントハンドラの中で Clipboard API を呼ぶ
という流れになっているので、
ブラウザは「ユーザーの意思に基づく操作」と判断しやすくなります。
ペースト(readText)も同じで、
pasteBtn.addEventListener("click", async () => {
const text = await navigator.clipboard.readText();
console.log(text);
});
JavaScriptのように、「ユーザーが今貼り付けたい」と示した瞬間にだけ
読み取りを試みるのが基本形です。
読み取りは「書き込み」よりさらに厳しく見られる
なぜ読み取りが特に厳しいのか
書き込み(コピー)は、
「ユーザーのクリップボードの中身を上書きする」操作です。
もちろんこれも重要ですが、
読み取り(ペースト)はもっと重いです。
読み取りは、
- ユーザーが何をコピーしたか
- どんなパスワードや個人情報を扱っているか
を、サイト側が知れてしまう可能性があるからです。
だからブラウザは、読み取りに対して特に厳しく、
- HTTPS であること
- ユーザー操作に紐づいていること
- 場合によっては権限ダイアログで「許可」されていること
といった条件を満たしていないと、navigator.clipboard.readText() を普通に失敗させます。
コードとしてはこう書きます。
pasteBtn.addEventListener("click", async () => {
try {
const text = await navigator.clipboard.readText();
console.log("クリップボード:", text);
} catch (err) {
console.error("読み取りに失敗しました:", err);
}
});
JavaScriptここで try...catch が必須なのは、
「セキュリティ制限で失敗することがある」のが前提だからです。
navigator.permissions と権限の状態(概念だけ知っておけばOK)
「このサイトにクリップボードを触らせていいか?」をブラウザが覚えている
一部のブラウザでは、navigator.permissions という API を通じて
権限の状態を問い合わせられることがあります。
概念としては、こんな感じです。
const status = await navigator.permissions.query({
name: "clipboard-read"
});
console.log(status.state); // "granted" / "prompt" / "denied" など
JavaScriptclipboard-write についても同様です。
ただし、これはブラウザ差が大きく、
すべての環境で同じように動くわけではありません。
初心者のうちは、
- Clipboard API を呼ぶ
- 失敗したら catch で対応する
というシンプルなパターンで十分です。
「権限の状態を事前に確認できることもある」
くらいの理解で OK です。
セキュリティ制限を前提にした「ちゃんとしたコード」の書き方
1. Clipboard API が使えるかどうかを最初に確認する
まずは、ブラウザが Clipboard API に対応しているかをチェックします。
if (!navigator.clipboard) {
console.log("このブラウザでは Clipboard API が使えません");
}
JavaScriptこれをやっておくと、
古いブラウザや特殊な環境での「そもそも無い」ケースを
きれいに弾けます。
2. 失敗する前提で try…catch を必ず書く
コピー処理の例をもう一度、
セキュリティ制限を意識して書き直すとこうなります。
const copyBtn = document.querySelector("#copyBtn");
const status = document.querySelector("#status");
copyBtn.addEventListener("click", async () => {
if (!navigator.clipboard) {
status.textContent = "このブラウザではコピー機能が使えません";
return;
}
try {
await navigator.clipboard.writeText("コピーしたい文字列");
status.textContent = "コピーしました";
} catch (err) {
status.textContent = "コピーに失敗しました: " + err;
}
});
JavaScriptここでやっているのは、
- API が存在するかチェック
- 実際に呼ぶときは
try...catchで囲む - 失敗したときにユーザーにちゃんと伝える
という「セキュリティ制限を前提にした書き方」です。
「悪い例」をイメージすると、制限の意味がよく分かる
ページを開いた瞬間にクリップボードを盗み見るコード
もし制限がなかったら、
こんなコードが書けてしまいます。
window.addEventListener("load", async () => {
const text = await navigator.clipboard.readText();
// サーバーに送信して盗む、など
});
JavaScriptユーザーは何もしていないのに、
ページを開いただけでクリップボードの中身が抜かれます。
これは完全にアウトです。
ブラウザのセキュリティ制限は、
こういうコードを「技術的に不可能にする」ために存在しています。
勝手にクリップボードを書き換えるコード
同じく、こんなコードも危険です。
setInterval(async () => {
await navigator.clipboard.writeText("このサイトの宣伝文");
}, 1000);
JavaScriptユーザーが何をコピーしても、
1秒ごとに上書きされてしまいます。
これも当然、
ブラウザのセキュリティ制限によって
現実には動かないようにされています。
こういう「悪い例」を頭の中で一度イメージしておくと、
「だから HTTPS が必要なんだ」
「だからユーザー操作に紐づけないとダメなんだ」
という理由が、感覚として腑に落ちてきます。
初心者として「セキュリティ制限」で本当に掴んでほしいこと
Clipboard API のセキュリティ制限は、
細かい仕様を全部覚える必要はありません。
まずは次の感覚だけ、しっかり持っておいてください。
クリップボードは、ユーザーの超プライベートな領域。
だからブラウザは「HTTPS」と「ユーザー操作」を条件にしている。
読み取りは特に厳しく、失敗することを前提に try...catch で書く。
「勝手に読まない・勝手に書き換えない」という倫理も含めて設計する。
そのうえで、次のようなコードを自分の手で書いてみてください。
ボタンを押したときだけテキストをコピーする処理(成功/失敗メッセージ付き)。
ボタンを押したときだけクリップボードの内容を読み取り、画面に表示する処理。
これが自然に書けるようになったとき、
セキュリティ制限は「邪魔な壁」ではなく、
「ユーザーとあなたのアプリの信頼を守るための、大事なルール」
として見えてくるはずです。
