關於瀏覽器的複製分頁功能
| | | 0 | |
接獲使用者通報才知 Edge 跟 Chrome 有個我沒用過的功能 - 「複製索引標籤」(Edge,下圖左)/「複製」分頁 (Chrome,下圖右)。

實測複製分頁會沿用相同 HTML 原始碼,欄位填寫內容也會被一起帶入新分頁,程式若未考慮此種操作情境,可能引發問題。
用以下 ASP.NET MVC 網頁重現問題,網頁有三個值,一個由 Razor 語法在伺服器端產生,一個為 JavaScript 動態生成,一個由使用者輸入:
@{
ViewData["Title"] = "Home";
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
margin: 10px;
font-size: 11pt;
}
a {
font-size: 12pt;
margin-left: 12px;
color: dodgerblue;
&:visited {
color: dodgerblue;
}
}
table {
border-collapse: collapse;
td {
border: 1px solid gray;
padding: 5px 10px;
}
td:first-child {
background-color: lightgray;
text-align: right;
}
input {
width: 100%;
padding: 5px;
box-sizing: border-box;
}
}
</style>
</head>
<body>
<h2>
「複製索引標籤」測試
<a href="" target="_blank">在新分頁開啟</a>
</h2>
<table>
<tr>
<td>Razor 值</td>
<td><span id="razorValue">@Guid.NewGuid().ToString()</span></td>
</tr>
<tr>
<td>JavaScript 值</td>
<td><span id="jsValue"></span></td>
</tr>
<tr>
<td>輸入欄位</td>
<td><input type="text" name="inputField" placeholder="Type somthing here..." /></td>
</tr>
</table>
<script>
const jsValue = Math.random().toString(16).substring(2);
document.getElementById("jsValue").innerText = jsValue;
</script>
</body>
</html>
按 <a href="" target="_blank"> 在新分頁開啟,三個值都會重新產生或等待輸入:

若使用複製分頁方式,可發現 Razor 值(伺服器端產生)及使用者輸入內容相同,僅 JavaScript 值會在每次顯示網頁時重新產生而不同:

若兩個分頁使用重複的伺服端生成值會導致問題(例如:該是唯一 GUID 值,不應從兩個分頁重複送出),有沒有辦法偵測這種複製分頁行為呢?
我想到一個簡單做法,借用 Broadcast Channel API,以 GUID 或唯一值作為頻道名詞廣播,若有另一個分頁使用相同 GUID 接收到廣播訊息,就代表有兩個分頁使用相同 GUID,視需求決定處置方式,例如:彈出警告、阻擋送出表單或禁止網頁操作... 等。
<script>
const uniqueId = document.getElementById("razorValue").innerText;
const channel = new BroadcastChannel(uniqueId);
// 正常情況不該收到來自此唯一值的廣播,若有代表初四了
channel.addEventListener("message", (event) => {
if (event.data === uniqueId) {
alert("偵測到重複分頁");
}
});
// 對唯一值頻道送出訊息
channel.postMessage(uniqueId);
</script>
測試成功。

Highlights Edge/Chrome “duplicate tab” behavior, showing how server-generated values and user inputs persist across duplicated tabs. Demonstrates risks with non-unique server IDs and proposes detecting duplicates using the Broadcast Channel API.
Comments
Be the first to post a comment