iT邦幫忙

2025 iThome 鐵人賽

DAY 11
1
Build on AWS

從一個網站的誕生,看懂 AWS 架構與自動化的全流程!系列 第 11

Day 11 安全機制再升級:Cognito 忘記密碼與 MFA 設定、黑名單禁止註冊

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250925/20172743qIsFCInHEu.png

一、前言

在會員系統中,單純的帳號密碼往往不足以確保安全性。必須提供 忘記密碼流程 以提升使用體驗,並且透過 MFA(多因子驗證) 強化安全,同時避免惡意使用者反覆以黑名單信箱或特定網域註冊帳號,確保服務穩定。

這個 Lab 針對「會員系統安全強化」:
(1) 提供使用者忘記密碼流程,避免密碼遺失造成帳號無法使用。
(2) 加入 MFA,確保登入過程多一層安全防護。
(3) 建立黑名單規則,避免濫用註冊(例如垃圾郵件網域、惡意 IP)。
此 Lab 在整體 Serverless 架構中,補足「會員註冊與登入流程」的安全與風險控管。

二、需要使用到的服務

  • Amazon Cognito User Pools:管理使用者帳號、登入、忘記密碼與 MFA 驗證邏輯。
  • AWS Lambda(PreSignUp Trigger):在註冊前自動檢查黑名單(郵件網域、IP)。
  • Amazon SES(選用):支援忘記密碼或驗證碼的郵件寄送。
  • CloudWatch Logs:追蹤黑名單攔截與 MFA 啟用狀態。

三、架構/概念圖

https://ithelp.ithome.com.tw/upload/images/20250925/20172743YfGVADzgVp.png

四、技術重點

(1) 建議使用 TOTP MFA(Google/Microsoft Authenticator),比 SMS 更安全。
(2) 黑名單應存放在 DynamoDBParameter Store,而非寫死在 Lambda 程式碼,方便維護。
(3) 建立 CloudWatch Alarm,監控黑名單註冊攔截的次數,避免有系統性攻擊。
(4) 若規模成長,可考慮結合 WAF + Bot Control 進一步過濾惡意流量。

五、Lab流程

1️⃣ 前置作業

  1. 確認 Cognito User Pool 已創建完成。(Day9)
  2. 確認 SES 已經過 Email 驗證(可用於寄送忘記密碼信件)。

2️⃣ 主要配置

1. 確認 Cognito User Pool 的App Client 權限已啟用

  1. 進入「Cognito」頁面。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743pO9Dd0Xbwi.png

  2. 進入Day9創建的Cognito。
    https://ithelp.ithome.com.tw/upload/images/20250925/201727436SZIN86Znt.png

  3. 編輯「應用程式用戶端資訊」。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743DEi66OS8j7.png

  4. 將兩個權限開啟。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743lu8xSm2jNH.png
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743SD4wSNPrTY.png

  5. 完成畫面
    https://ithelp.ithome.com.tw/upload/images/20250925/201727437TNXiTmPAI.png

2. 啟用使用者帳戶恢復(忘記密碼)的功能

https://ithelp.ithome.com.tw/upload/images/20250925/2017274304ggigerZu.png

3. 啟用Cognito 的 MFA驗證

  1. 進入Cognito,選擇「登入」的設定,在多重要素驗證點選「編輯」。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743ypiS5StVmu.png

  2. 選擇要選用的MFA方法。(勾選其中一種,後面「測試」的章節分別有兩種方式的測試情境)
    💡MFA方法同時選用「驗證器應用程式」及「電子郵件訊息」時,系統會優先採用「電子郵件訊息」。
    故建議使用其中一種即可。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743hrlcnTdnVo.png

  3. 將電子郵件組態改為以「SES」傳送電子郵件。(註冊驗證碼信件)
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743fkaa32sgVS.png

  4. 繼續完成MFA設定。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743Qa2FqlRbQC.png

  5. 完成畫面。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743iVdQb1VQE4.png

4. 建立黑名單Lambda動作

  1. 進入「Lambda」頁面。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743wCIo2Hx5Fi.png

  2. 創建一個新的函數。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743UqisBOOlDa.png

  3. 輸入函數名稱,並選擇編撰語言。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743lTKwlCQ3oh.png

  4. 跳過建議畫面。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743Zn3l0VweOB.png

  5. 寫入程式碼,並部署。

    • 程式碼範例

      // preSignUpBlacklist.js
      // 使用 AWS SDK V3
      import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm";
      
      const ssmClient = new SSMClient({});
      const blacklistParameterName = '/app/blacklist/domain';
      
      export const handler = async (event) => {
          const email = event.request.userAttributes.email;
      
          try {
              // 從 Parameter Store 讀取黑名單參數
              const command = new GetParameterCommand({
                  Name: blacklistParameterName,
                  WithDecryption: true
              });
              const parameter = await ssmClient.send(command);
      
              // 將逗號分隔的字串轉換成陣列
              const blacklistedDomains = parameter.Parameter.Value.split(',');
      
              const domain = email.split('@')[1];
              if (blacklistedDomains.includes(domain)) {
                  // 如果 Email 網域在黑名單中,則拋出錯誤
                  console.log(`Blocked registration from blacklisted domain: ${email}`);
                  throw new Error('Email domain is not allowed.');
              }
      
              // 允許註冊
              console.log(`Allowing registration for: ${email}`);
              return event;
      
          } catch (err) {
              // 處理 SSM 錯誤,例如參數不存在
              if (err.name === 'ParameterNotFound') {
                  console.warn(`Parameter '${blacklistParameterName}' not found. No blacklisting applied.`);
                  return event; // 繼續允許註冊
              }
      
              // 處理其他錯誤
              console.error('Error in pre-signup Lambda:', err);
              throw err;
          }
      };
      
      

    https://ithelp.ithome.com.tw/upload/images/20250925/20172743CEaZ6pckhG.png

5. 從Cognito觸發黑名單禁止註冊的Lambda動作

  1. 在「延伸功能」分頁中,添加Lambda觸發。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743OOGhwsc5Rr.png

  2. 將觸發動作與Lambda函數設定好。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743X6xx4cFBnu.png

  3. 完成畫面。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743EOtT9DA65S.png

6. 編輯被關聯的黑名單名單

  1. 進入「Systems Manager」頁面。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743LN6c2cdsqY.png

  2. 建立一個新的參數。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743L0cFUfEOT3.png

  3. 設定參數名稱「app/blacklist/domain」,值為域名黑名單,中間可用「,」做分隔。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743wHz4sGoF0q.png
    https://ithelp.ithome.com.tw/upload/images/20250925/201727438pg6K11uY7.png

7. 授予Lambda role存取參數的權限

  1. 進入「IAM 」頁面。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743T9XHPuJ7DF.png

  2. 進入IAM role的頁面,點選該Lambda自動創建的IAM role。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743HNcO76DmA8.png

  3. 新增「許可政策」。
    https://ithelp.ithome.com.tw/upload/images/20250925/201727431gzbytTVEK.png

  4. 增加SSM的「GetParameter」權限,授權資源為指定的「Systems Manager」。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743IvuN94hONE.png

  5. 貼上Systems Manager的ARN,並點選「新增」。
    https://ithelp.ithome.com.tw/upload/images/20250925/201727437S9IqYZcl7.png
    - Systems Manager的ARN要去哪裡看?
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743yhK8qfArph.png

  6. 點選下一步。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743Sh5qJ82jvK.png

  7. 設定「許可政策」名稱。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743SuJN7Yt0d9.png

  8. 創建完成畫面。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743JZBlMfdqUh.png

3️⃣ 測試驗證

1. 使用合法 Email 測試忘記密碼流程,確認能收到驗證碼並重設成功。

💡當「多重要素驗證」的MFA方法選用「驗證器應用程式」時,才可以成功寄驗證碼並重置密碼。
https://ithelp.ithome.com.tw/upload/images/20250925/20172743Pjc44rV9k9.png

  1. 在 Cognito Console → App client settings → 啟用「Forgot Password」功能。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743lKtPuJDjc1.png

  2. 跳轉到該畫面,並會收到驗證信。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743VAosqKW5er.png

3.驗證信範例
https://ithelp.ithome.com.tw/upload/images/20250925/201727434AKtnLGHNI.png
4. 重設密碼。
https://ithelp.ithome.com.tw/upload/images/20250925/20172743Cq9tfbbSH2.png

2. 使用管理者後台(AWS帳號內的Cognito)重設user密碼

https://ithelp.ithome.com.tw/upload/images/20250925/20172743roGe9Emrg2.png

3. 使用 Cognito Hosted UI 或 SDK 呼叫 ForgotPassword API,系統會自動寄出驗證碼至使用者信箱。

API參考連結:https://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/cognito-identity-provider_example_cognito-identity-provider_ForgotPassword_section.html

4. MFA驗證器啟用後測試

  1. 刪除原本的使用者。

  2. 重新註冊,會收到來自SES網域的來信。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743IOM3BF6mEA.png

  3. 進入MFA設定畫面。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743oHIXeUOduU.png

  4. 綁定MFA裝置。
    https://ithelp.ithome.com.tw/upload/images/20250925/201727437QXYwblZej.png

  5. 下次登入需要輸入MFA設備驗證碼。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743CbOEtQ0yK3.png

  6. 成功登入。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743R53YJnsPFd.png

5. MFA信箱啟用後測試

  1. 刪除原本的使用者。

  2. 重新註冊,會收到來自SES網域的來信(信箱驗證碼)。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743fCe30yadLW.png

  3. 收到E-mail MFA驗證信
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743M75yrtsrWS.png

  4. 輸入帳密後,會需要再輸入E-mail MFA code。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743RGK0injJTj.png

  5. 成功登入。
    https://ithelp.ithome.com.tw/upload/images/20250925/201727434BtV1XjlQC.png

6. 嘗試使用黑名單網域 Email 註冊,應該會遭到 Lambda 拒絕。

  1. 使用黑名單的網域註冊。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743sdXxuRRgS8.png

  2. 發現被Cognito阻擋、無法成功註冊。
    https://ithelp.ithome.com.tw/upload/images/20250925/20172743vESkriiasc.png

六、結語

本 Lab 強化 Cognito 會員系統的安全性,實現了忘記密碼機制、MFA 多因子驗證,以及透過 Lambda PreSignUp 黑名單防護的註冊過濾。這不僅提升了使用者體驗,也保障了系統的安全與穩定,符合雲端應用的最佳實踐。


七、參考資料

八、補充說明

  • 簡單說明

    • ALLOW_USER_PASSWORD_AUTH 讓使用者可以登入。
    • ALLOW_REFRESH_TOKEN_AUTH 讓使用者登入後可以長時間保持登入狀態,而不需要頻繁重新驗證。
  • 詳細說明

    1. 允許使用者帳號與密碼驗證 (ALLOW_USER_PASSWORD_AUTH)

    這個選項是基本登入流程的開關。當您啟用它時,您的應用程式才能使用使用者提供的帳號(例如電子郵件或使用者名稱)和密碼,向 Cognito 進行驗證並換取存取權杖(Access Token)。

    如果這個選項沒有啟用,應用程式就無法執行基本的登入請求,使用者也無法用他們設定的密碼來登入。

    2. 允許重新整理權杖驗證 (ALLOW_REFRESH_TOKEN_AUTH)

    這個選項則負責使用者體驗的持久性。在 OAuth 2.0/OIDC 架構中,為了安全起見,access_token 通常只有很短的生命週期(例如 1 小時)。當 access_token 過期後,使用者會被強制登出,需要重新輸入帳號密碼。

    refresh_token 的作用就是解決這個問題。當您啟用 ALLOW_REFRESH_TOKEN_AUTH 後,應用程式可以用 refresh_token 去換取新的 access_token,而不需要使用者再次輸入密碼。這讓使用者可以長時間保持登入狀態,大幅提升了使用的便利性。


上一篇
Day 10 會員信件自動寄送:Lambda x SES 打造註冊通知
系列文
從一個網站的誕生,看懂 AWS 架構與自動化的全流程!11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言