在會員系統中,單純的帳號密碼往往不足以確保安全性。必須提供 忘記密碼流程 以提升使用體驗,並且透過 MFA(多因子驗證) 強化安全,同時避免惡意使用者反覆以黑名單信箱或特定網域註冊帳號,確保服務穩定。
這個 Lab 針對「會員系統安全強化」:
(1) 提供使用者忘記密碼流程,避免密碼遺失造成帳號無法使用。
(2) 加入 MFA,確保登入過程多一層安全防護。
(3) 建立黑名單規則,避免濫用註冊(例如垃圾郵件網域、惡意 IP)。
此 Lab 在整體 Serverless 架構中,補足「會員註冊與登入流程」的安全與風險控管。
(1) 建議使用 TOTP MFA(Google/Microsoft Authenticator),比 SMS 更安全。
(2) 黑名單應存放在 DynamoDB 或 Parameter Store,而非寫死在 Lambda 程式碼,方便維護。
(3) 建立 CloudWatch Alarm,監控黑名單註冊攔截的次數,避免有系統性攻擊。
(4) 若規模成長,可考慮結合 WAF + Bot Control 進一步過濾惡意流量。
進入「Cognito」頁面。
進入Day9創建的Cognito。
編輯「應用程式用戶端資訊」。
將兩個權限開啟。
完成畫面
進入Cognito,選擇「登入」的設定,在多重要素驗證點選「編輯」。
選擇要選用的MFA方法。(勾選其中一種,後面「測試」的章節分別有兩種方式的測試情境)
💡MFA方法同時選用「驗證器應用程式」及「電子郵件訊息」時,系統會優先採用「電子郵件訊息」。
故建議使用其中一種即可。
將電子郵件組態改為以「SES」傳送電子郵件。(註冊驗證碼信件)
繼續完成MFA設定。
完成畫面。
進入「Lambda」頁面。
創建一個新的函數。
輸入函數名稱,並選擇編撰語言。
跳過建議畫面。
寫入程式碼,並部署。
程式碼範例
// 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;
}
};
在「延伸功能」分頁中,添加Lambda觸發。
將觸發動作與Lambda函數設定好。
完成畫面。
進入「Systems Manager」頁面。
建立一個新的參數。
設定參數名稱「app/blacklist/domain」,值為域名黑名單,中間可用「,」做分隔。
進入「IAM 」頁面。
進入IAM role的頁面,點選該Lambda自動創建的IAM role。
新增「許可政策」。
增加SSM的「GetParameter」權限,授權資源為指定的「Systems Manager」。
貼上Systems Manager的ARN,並點選「新增」。
- Systems Manager的ARN要去哪裡看?
點選下一步。
設定「許可政策」名稱。
創建完成畫面。
💡當「多重要素驗證」的MFA方法選用「驗證器應用程式」時,才可以成功寄驗證碼並重置密碼。
在 Cognito Console → App client settings → 啟用「Forgot Password」功能。
跳轉到該畫面,並會收到驗證信。
3.驗證信範例
4. 重設密碼。
ForgotPassword
API,系統會自動寄出驗證碼至使用者信箱。API參考連結:https://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/cognito-identity-provider_example_cognito-identity-provider_ForgotPassword_section.html
刪除原本的使用者。
重新註冊,會收到來自SES網域的來信。
進入MFA設定畫面。
綁定MFA裝置。
下次登入需要輸入MFA設備驗證碼。
成功登入。
刪除原本的使用者。
重新註冊,會收到來自SES網域的來信(信箱驗證碼)。
收到E-mail MFA驗證信
輸入帳密後,會需要再輸入E-mail MFA code。
成功登入。
使用黑名單的網域註冊。
發現被Cognito阻擋、無法成功註冊。
本 Lab 強化 Cognito 會員系統的安全性,實現了忘記密碼機制、MFA 多因子驗證,以及透過 Lambda PreSignUp 黑名單防護的註冊過濾。這不僅提升了使用者體驗,也保障了系統的安全與穩定,符合雲端應用的最佳實踐。
AWS Cognito - 使用 AWS SDKs 的 Amazon Cognito 身分提供者基本範例:
簡單說明
ALLOW_USER_PASSWORD_AUTH
讓使用者可以登入。ALLOW_REFRESH_TOKEN_AUTH
讓使用者登入後可以長時間保持登入狀態,而不需要頻繁重新驗證。詳細說明
這個選項是基本登入流程的開關。當您啟用它時,您的應用程式才能使用使用者提供的帳號(例如電子郵件或使用者名稱)和密碼,向 Cognito 進行驗證並換取存取權杖(Access Token)。
如果這個選項沒有啟用,應用程式就無法執行基本的登入請求,使用者也無法用他們設定的密碼來登入。
這個選項則負責使用者體驗的持久性。在 OAuth 2.0/OIDC 架構中,為了安全起見,access_token
通常只有很短的生命週期(例如 1 小時)。當 access_token
過期後,使用者會被強制登出,需要重新輸入帳號密碼。
refresh_token
的作用就是解決這個問題。當您啟用 ALLOW_REFRESH_TOKEN_AUTH
後,應用程式可以用 refresh_token
去換取新的 access_token
,而不需要使用者再次輸入密碼。這讓使用者可以長時間保持登入狀態,大幅提升了使用的便利性。