由於我公司有使用玉山商業銀行來處理帳務,我經常需要登入玉山全球智匯網以審核放行一些廠商款項,我一直以來都有使用密碼管理器的習慣,確保我的每個網站所使用的密碼都是不一樣的,強化資訊安全。不過,該網站在我用了數幾年之後,從不久之前開始,該網站完全無法自動登入了,深入研究後才發現,原來他們把網頁上的表單欄位的 id
屬性移除了!這篇文章我來說說我解決此問題的過程,也說說前端工程師應注意的事項!
問題分析
由於很少有網站無法使用「密碼管理器」來管理密碼,玉山全球智匯網應該是我第一個遇到完全無法自動輸入密碼的網站,所以我就分析了一下這個網站的前端結構,以下是我的探索發現:
-
我很驚訝的發現,該網站的首頁竟然用了一個我從 2000
年開始就沒在用的標籤 FRAMESET
標籤!😅
我不太清楚這個設計的用意為何?故意讓網站上的網址不會動嗎?好多銀行都有類似設計,我聽過大多數的原因,都是不希望客戶按下 F5 重新整理網頁,只要按了 F5 重新整理網頁就要登出!但我必須老實說,你其實有更好的選擇,可以不用透過 FRAMESET
來降低網頁的可及性(Accessibility)!
-
我拿掉了 FRAMESET 的包袱,直接進入 FRAMESET 中的主要頁面,網頁依然可以正常瀏覽!
他們用了 Angular 4.4.6
版本來建置這個網站,可以理解從建站之初到現在,從來沒有升級過版本,老實說我會擔心使用太舊版本的前端框架或函式庫,會帶來一些資訊安全上的風險。
題外話,網頁上載入的 JavaScript 刻意加上 defer
與 async
在這裡是完全無意義的,這個位置已經在頁尾了阿!😅
-
我的密碼管理器自動填入了「使用者名稱」與「密碼」欄位,但是「顧客ID/代號」這個欄位就沒有自動填入了!
因為這個網站我已經用了很多年,這個欄位一直是可以填入的,但前幾個月似乎就開始無法自動填入了。
-
原來「顧客ID/代號」這個欄位缺乏 id
屬性,導致密碼管理器無法定位到該欄位!
我想這就是主因了,一定是在某次更版的過程中,開發人員將 id
屬性移除了。老實說,在 SPA 架構下,表單欄位的 id
與 name
屬性其實一點都不重要,沒有這兩個屬性一樣可以開發表單互動,所以經常被開發人員忽略。
在網頁中的標籤使用 id
屬性,除了可以讓傳統 JavaScript 更好的透過 DOM API 定位到該元素(Element)之外,還可以讓 E2E 自動化測試更好的定位到該欄位。很自然的,此舉也可以讓「密碼管理器」更容易找到重要的表單欄位,加以記憶與管理!
解決方案
解決這個問題其實也不難,透過 Tampermonkey 擴充套件,外加我寫的一段 Userscript 就可以在網頁載入時自動加入該欄位的 id
屬性,如此一來「密碼管理器」就可以識別這個欄位了!👍
以下是完整的 Userscript 實作:
// ==UserScript==
// @name 玉山銀行: 添加遺失的表單欄位 id 屬性
// @version 1.0.0
// @description 修復玉山銀行玉山全球智匯網登入頁面無法使用密碼管理器的問題
// @license MIT
// @homepage https://blog.miniasp.com/
// @homepageURL https://blog.miniasp.com/
// @website https://www.facebook.com/will.fans
// @source https://github.com/doggy8088/TampermonkeyUserscripts/raw/main/src/ESUN_Add_Field_ID.user.js
// @namespace https://github.com/doggy8088/TampermonkeyUserscripts/raw/main/src/ESUN_Add_Field_ID.user.js
// @match https://gib.esunbank.com/*
// @author Will Huang
// @run-at document-start
// @icon https://www.google.com/s2/favicons?sz=64&domain=https://gib.esunbank.com
// ==/UserScript==
(async function () {
"use strict";
let it = setInterval(() => {
let elm = document.querySelector('input[placeholder="顧客ID/代號"],input[placeholder="顾客ID/代号"],input[placeholder="Customer ID/No"]');
if (elm) {
elm.id = 'inputCustomerId';
clearInterval(it);
}
}, 60);
})();
後記
其實我可以理解銀行的資安需求永遠站在最高標準看待,我覺得他們應該是站在保護顧客的立場,不希望客戶透過「任何工具」代客戶輸入密碼。不過我老實說,如果真的有這種想法,這個資安觀念真的是有點過時了,就跟要求客戶每半年要改一次密碼,而且不能用過去 5 次用過的密碼一樣過時!
現在上網風險之高,已經跟 20 年前不太一樣了,撞庫攻擊是常年下來一直都非常有效的攻擊手段,因此在不同網站之間共用相同密碼,早就被證明是一種相當危險的密碼管理政策,應該盡可能的避免。若網站要求使用者經常變更密碼,又不允許他們使用工具輸入密碼,這無疑是要人把密碼貼在鍵盤底下,不然就是設定「一二兩排」這種 IT 人常見的「高強度密碼」!😆
這篇文章希望可以讓使用任何 JS 前端框架的開發者知道,適時的加上 id
屬性到欄位上,其實可以減少用戶的麻煩,提高用戶滿意度,更能提升資安強度!👍
喔喔,還有,拜託 <frameset>
不要再用了!事實上在 HTML5 規格中,根本沒有這個標籤,這是一個 W3C 完全棄用的歷史產物,瀏覽器為了讓老舊網頁還可以瀏覽,所以才留著的。網站做這麼棒,花了那麼多力氣在 UI/UX 上面,我覺得用現代化的角度去製作網站(Modern Web),應該是全體 Web 開發者的共識啦,不鼓勵再去使用任何已廢棄的 HTML 標籤或 Web API!🔥
相關連結