🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

前言

當自己想要製作一個網頁並實現登入功能時,是否曾經面對過這樣的疑問呢?

  • 可以直接保存密碼嗎?
  • 登入後,若直接輸入網址是否會不需要登入就能進入?
  • 那麼「登入狀態」究竟是如何維持的呢?

平常我們習以為常的登入功能,其背後其實隱藏著一些不為人知的原理。本文將解釋登入認證的基本機制。

僅靠 HTML/CSS 無法管理登入狀態

其實,HTML/CSS 本身並不具備確認登入狀態的功能。更精確地說,因為網路的基礎 HTTP 協議本身是「無狀態的」

HTTP 的無狀態性是什麼?

HTTP 為每個從客戶端(瀏覽器)發出的請求進行獨立的通訊。也就是說:

  • 第一次請求:「請給我登入頁面」
  • 第二次請求:「請給我我的頁面」

這兩個請求在 HTTP 的運作上被視為完全無關的獨立通訊。伺服器無法自動識別「剛才訪問的人與現在的是同一個人」。

image.png

這樣一來就無法維持「登入狀態」。那麼,實際的網站是如何維持登入狀態的呢?

Cookie 與 Session 管理的機制

答案在於 Cookie(曲奇)與 Session 管理

Cookie 是什麼?

Cookie 是由伺服器發送到瀏覽器的小數據,並保存於瀏覽器中。重要的是,瀏覽器會在下次請求時自動將存儲的 Cookie 發送回伺服器

利用這個機制來維持「登入狀態」。

透過 Session ID 的認證流程

讓我們來看看具體的流程。

image.png

重點

  1. 登入時:伺服器生成隨機字符串(Session ID),並保存於資料庫中
  2. 透過 Cookie 發送:將該 Session ID 作為 Cookie 發送到瀏覽器
  3. 瀏覽器保存:瀏覽器保存 Cookie
  4. 之後的請求:瀏覽器每次自動發送 Cookie
  5. 伺服器驗證:伺服器確認 Session ID 的有效性並進行認證

解決 URL 直打問題的方法

「登入後的頁面如果直接輸入網址,是否會不需登入就能進入?」這個問題透過 伺服器端的 Session 驗證來解決。

安全性要點

  • 所有受保護的頁面都必須進行 Session 驗證
  • 對 Session 設定 有效期限
  • 當 Session 無效時,必定重定向至登入頁面
  • 不僅僅是在客戶端(JavaScript),還必須在 伺服器端進行驗證

這樣就能持續判定是否已登入,未認證的使用者將被攔截於受保護的頁面之外。

其他安全注意事項

在了解登入的機制後,還需談及一些關鍵的安全問題。
如果存在安全漏洞,可能會被他人冒充或導致個人資訊被竊取。

實作運行與安全是兩回事,因此自一開始就必須具備安全性的設計意識

1. 密碼絕不能以明文保存

為什麼明文保存會有問題?

如果將密碼直接(明文)保存於資料庫中:

-- ❌ 絕對不應該這樣做的例子
INSERT INTO users (email, password) 
VALUES ('[email protected]', 'mypassword123');

這樣做會導致:

  1. 若資料庫洩露,所有使用者的密碼將暴露無遺
  2. 管理者或開發者也能查看使用者的密碼
  3. 若在其他網站使用相同密碼,那麼也將面臨風險

通過哈希處理安全保存

密碼應使用 哈希函數 進行單向轉換(哈希化)後再保存。
對於不太了解哈希化的人,可以簡單記住,「以無法回覆的形式進行轉換」

加密是可解密的,而哈希化是單向轉換無法解密的。

// 擬似代碼例
const bcrypt = require('bcrypt');

// 使用者註冊時
const password = 'mypassword123';
const saltRounds = 10;
const passwordHash = await bcrypt.hash(password, saltRounds);

// 保存至資料庫
db.query(
    'INSERT INTO users (email, password_hash) VALUES (?, ?)',
    ['[email protected]', passwordHash]
);

// 保存的例子:$2b$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy

哈希化的特性

  • 單向轉換:無法從哈希值恢復出原始密碼
  • 相同輸入→相同輸出:相同的密碼會產生相同的哈希值
  • 微小變化卻有巨大差異:相似的密碼會得到完全不同的哈希值

2. 不能在 Cookie 中保存機密信息

Cookie 中僅能保存 Session ID,不應保存個人資訊或機密信息。
若將個人資訊或機密情報放在裡面,每次都會被發送到網絡上,增加洩露的風險

如果 httpOnly 未設置,JavaScript 可能會被竊取;若未設置 secure,則可能在非 HTTPS 的路徑中洩露。

因此,Cookie 也需設置適當的安全選項,將機密信息保存於資料庫中。

Cookie 的安全選項

選項 說明
httpOnly 禁止 JavaScript 訪問(防範 XSS)
secure 僅在 HTTPS 通信中發送 Cookie
sameSite 限制跨網站請求中的 Cookie 發送(防範 CSRF)
maxAge 設定 Cookie 的有效期限

3. 強制使用 HTTPS 通信

Session ID 必須透過 HTTPS 發送,否則在中間人攻擊中可能會被竊取。
HTTP 通信沒有加密,即便最終的形式經過加密,但若在途中被竊取,機密信息仍會洩露。

4. 防止 Session 劫持

Session 劫持是指竊取 Session ID 然後冒充正規使用者的攻擊。
即便密碼安全,若 Session ID 被得知,仍可訪問受保護的頁面。

正如前面所述,Session ID 是由 Cookie 管理的,因此安全性相較於密碼要低。

因此,對於 Session ID 我們還需採取如下的安全對策。

  • Session ID 必須是 足夠隨機且無法猜測
  • 登入成功後 重新生成 Session ID
  • 對 Session 設定 有效期限
  • 登出時務必 銷毀 Session

總結

  1. HTTP 是無狀態的,因此在狀態管理上需要一些技巧
  2. Cookie + Session ID 來維持登入狀態
  3. 密碼必須進行哈希化 保存於資料庫中
  4. 透過 Session 驗證,在直接輸入網址時亦可防範未經授權的訪問
  5. Cookie 中不得保存機密資訊(僅保存 Session ID)
  6. HTTPS 通信 及適當的安全設置是必須的

原文出處:https://qiita.com/shibata1111/items/855524191d08f73a6748


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝7   💬6   ❤️2
170
🥈
我愛JS
💬1  
6
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付