2024年3月18日 星期一

在前端寫後端?如何寫出不會被快取清掉的資料

前言

前陣子接到一個需求,要前端產出一個uuid,傳給後端當身份驗正。先別噴,身份驗證坐在前端前所未聞,但任務確實就是這樣,開發過前端的都知道,前端存資料選項沒幾個,就算我把資料存local storage,一但遇到清除快取也會消失。一開始PM那邊當然是說沒關係,我們盡量,但背後還是不斷給壓力說看有沒有辦法解決......這擺明就是後端的工作,我實在想不明白為什麼必須得前端做想,他們困難點到底在哪,相當然爾我兩手一攤說沒有辦法,結果主管有天突然就跳出來了說他想到更好的方法了!!

我們先來解釋一下他的想法,簡單說把產生uuid的做成單獨的一個站,然後除了存入local storage之外,還要用postMessage的方式將產生的uuid回傳,看到這裡聰明的小夥伴應該猜到,在原專案用iframe將上面這個站嵌入就可以了,變且addEventListener("message", (e) => { e.data })去監聽回傳內容就好。

這樣除非對方真的很專業開啟了產生uuid的站並清除快取,不然在原本的站怎麼清uuid都會保持不變,我附上code

// uuid page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SSO Page</title>
</head>
<body>
<script>
function generateUUID() {
var d = new Date().getTime();
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
d += performance.now(); // 使用性能計時器來增加隨機性
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}
var uuid = localStorage.getItem('uuid');
if(!uuid){
uuid = generateUUID();
localStorage.setItem('uuid', uuid);
}
// 發送 local storage 中的數據給父頁面
window.parent.postMessage(uuid, document.referrer);
</script>
</body>
</html>


// parent page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Parent Page</title>
</head>
<body>
<iframe src="https://uuid.com" width="1" height="1" style="display:none"></iframe>
<script>
// 接收來自子 iframe 的消息
window.addEventListener('message', function(event) {
  console.log(event.data) // uuid
}, false);
</script>
</body>
</html>

後記

我雖然滿佩服主管可以想到這種奧步的,且這招不光是只能用來存資料,也可以拿來做些偷雞摸狗的事情,例如我第一分工作就看到老闆使用iframe更新主頁面的畫面.......某種意義上來說也是ajax拉,把部分後端的工作移到前端來做。不考量安全性的話......天啊,我好不想想起當時那個畫面==大家還是考量一下安全性,珍惜生命,少用iframe吧

沒有留言:

張貼留言