ASP.NET MVC 5 應用程式使用 SMS 和電子郵件 Two-Factor 驗證
本教學課程說明如何使用 Two-Factor 驗證建置 ASP.NET MVC 5 Web 應用程式。 您應該完成 建立安全 ASP.NET MVC 5 Web 應用程式,並登入、電子郵件確認和密碼重設,再繼續進行。 您可以在這裡下載已完成的應用程式 ,。 下載包含偵錯協助程式,可讓您測試電子郵件確認和簡訊,而不需設定電子郵件或 SMS 提供者。
本教學課程由 里克·安德森 撰寫(Twitter:@RickAndMSFT)。
建立 ASP.NET MVC 應用程式
從安裝並執行 Visual Studio Express 2013 for Web 或更高版本開始。
注意
警告:您應該完成 建立具有登入、電子郵件確認和密碼重設 的安全 ASP.NET MVC 5 Web 應用程式,再繼續進行。 您必須安裝 Visual Studio 2013 Update 3 或更高版本,才能完成本教學課程。
- 建立新的 ASP.NET Web 專案,然後選取 MVC 範本。 Web Forms 也支援 ASP.NET 身分識別,因此您可以遵循 Web 窗體應用程式中的類似步驟。
- 將預設驗證保留為 個別用戶帳戶。 如果您想要在 Azure 中裝載應用程式,請保留複選框。 稍後在本教學課程中,我們將部署至 Azure。 您可以免費 開啟Azure 帳戶。
- 將 項目設定為使用 SSL。
為雙因素驗證設置SMS功能
本教學課程提供使用 Twilio 或 ASPSMS 的指示,但您可以使用任何其他 SMS 提供者。
使用SMS提供者建立用戶帳戶
安裝其他套件或新增服務參考
Twilio:
在套件管理員控制台中,輸入下列命令:
Install-Package Twilio
ASPSMS:
需要新增下列服務參考:位址:
https://webservice.aspsms.com/aspsmsx2.asmx?WSDL
Namespace:
ASPSMSX2
找出 SMS 提供者使用者認證
我們建議使用最安全的驗證選項。 如需部署至 Azure 的 .NET 應用程式,請參閱:
Azure Key Vault 和 .NET Aspire 提供最安全的方式來儲存和擷取秘密。 Azure Key Vault 是一項雲端服務,可保護加密密鑰和秘密,例如憑證、連接字串和密碼。 如需 .NET Aspire,請參閱 主機與用戶端整合間的安全通訊。
請避免資源擁有者密碼憑證授權,因為:
- 將使用者的密碼公開給用戶端。
- 這是一個重大的安全性風險。
- 只有在無法執行其他驗證流程時,才應該使用。
當應用程式部署至測試伺服器時,環境變數可用來將連接字串設定為測試資料庫伺服器。 環境變數通常會以純文字、未加密的文字儲存。 如果計算機或進程遭到入侵,則不受信任的合作物件可以存取環境變數。 建議您不要使用環境變數來儲存生產連接字串,因為它不是最安全的方法。
設定資料指導方針:
- 請勿將密碼或其他敏感數據儲存在組態提供者程式代碼或純文本組態檔中。
- 請勿在開發或測試環境中使用生產秘密。
- 指定專案外部的密碼,以避免不小心提交到原始碼庫中。
Twilio:
從 Twilio 帳戶的 [儀錶板] 索引標籤中,複製 帳戶 SID 和 驗證令牌。
ASPSMS:
從您的帳戶設定中,流覽至 Userkey,並將它與您的自我定義 密碼一起複製。
我們稍後會將這些值儲存在 web.config 檔案中的索引鍵 "SMSAccountIdentification"
和 "SMSAccountPassword"
。
4. 指定發件人ID(SenderID)/ 起始地(Originator)
Twilio:
從 [號碼] 索引標籤中,複製您的 Twilio 電話號碼。
ASPSMS:
在 [解除鎖定發送者 功能表內,解鎖一個或多個發送者,或選擇英數字發送者(並非所有網路皆支援)。
我們稍後會將此值儲存在金鑰 內的 "SMSAccountFrom"
檔案中。
5. 將 SMS 提供者認證傳輸至應用程式
使應用程式能夠取得憑證和發件者電話號碼。 為了保持簡單,我們會將這些值儲存在 web.config 檔案中。 當我們部署至 Azure 時,我們可以將值安全地儲存在網站設定索引標籤上的 [應用程式設定] 區段 區段中。
[!code-xml[Main](aspnet-mvc-5-app-with-sms-and-email-two-factor-authentication/samples/sample1.xml?highlight=8-10)]
> [!WARNING]
> Security - Never store sensitive data in your source code. The account and credentials are added to the code above to keep the sample simple. See [Best practices for deploying passwords and other sensitive data to ASP.NET and Azure](../../../identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure.md).
將數據傳輸至SMS服務提供商的實作
在
SmsService
檔案中設定 類別。根據所使用的 SMS 提供者,啟用 Twilio 或 ASPSMS 區段:
public class SmsService : IIdentityMessageService { public Task SendAsync(IdentityMessage message) { // Twilio Begin //var accountSid = ConfigurationManager.AppSettings["SMSAccountIdentification"]; //var authToken = ConfigurationManager.AppSettings["SMSAccountPassword"]; //var fromNumber = ConfigurationManager.AppSettings["SMSAccountFrom"]; //TwilioClient.Init(accountSid, authToken); //MessageResource result = MessageResource.Create( //new PhoneNumber(message.Destination), //from: new PhoneNumber(fromNumber), //body: message.Body //); ////Status is one of Queued, Sending, Sent, Failed or null if the number is not valid //Trace.TraceInformation(result.Status.ToString()); ////Twilio doesn't currently have an async API, so return success. //return Task.FromResult(0); // Twilio End // ASPSMS Begin // var soapSms = new MvcPWx.ASPSMSX2.ASPSMSX2SoapClient("ASPSMSX2Soap"); // soapSms.SendSimpleTextSMS( // System.Configuration.ConfigurationManager.AppSettings["SMSAccountIdentification"], // System.Configuration.ConfigurationManager.AppSettings["SMSAccountPassword"], // message.Destination, // System.Configuration.ConfigurationManager.AppSettings["SMSAccountFrom"], // message.Body); // soapSms.Close(); // return Task.FromResult(0); // ASPSMS End } }
更新 Views\Manage\Index.cshtml Razor 檢視:(注意:不要只移除現有程式代碼中的批注,請使用下列程式代碼。)
@model MvcPWy.Models.IndexViewModel @{ ViewBag.Title = "Manage"; } <h2>@ViewBag.Title.</h2> <p class="text-success">@ViewBag.StatusMessage</p> <div> <h4>Change your account settings</h4> <hr /> <dl class="dl-horizontal"> <dt>Password:</dt> <dd> [ @if (Model.HasPassword) { @Html.ActionLink("Change your password", "ChangePassword") } else { @Html.ActionLink("Create", "SetPassword") } ] </dd> <dt>External Logins:</dt> <dd> @Model.Logins.Count [ @Html.ActionLink("Manage", "ManageLogins") ] </dd> <dt>Phone Number:</dt> <dd> @(Model.PhoneNumber ?? "None") [ @if (Model.PhoneNumber != null) { @Html.ActionLink("Change", "AddPhoneNumber") @: | @Html.ActionLink("Remove", "RemovePhoneNumber") } else { @Html.ActionLink("Add", "AddPhoneNumber") } ] </dd> <dt>Two-Factor Authentication:</dt> <dd> @if (Model.TwoFactor) { using (Html.BeginForm("DisableTwoFactorAuthentication", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { @Html.AntiForgeryToken() <text>Enabled <input type="submit" value="Disable" class="btn btn-link" /> </text> } } else { using (Html.BeginForm("EnableTwoFactorAuthentication", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { @Html.AntiForgeryToken() <text>Disabled <input type="submit" value="Enable" class="btn btn-link" /> </text> } } </dd> </dl> </div>
確認
EnableTwoFactorAuthentication
中的DisableTwoFactorAuthentication
和ManageController
動作方法具有[ValidateAntiForgeryToken] 屬性:// // POST: /Manage/EnableTwoFactorAuthentication [HttpPost,ValidateAntiForgeryToken] public async Task<ActionResult> EnableTwoFactorAuthentication() { await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true); var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); if (user != null) { await SignInAsync(user, isPersistent: false); } return RedirectToAction("Index", "Manage"); } // // POST: /Manage/DisableTwoFactorAuthentication [HttpPost, ValidateAntiForgeryToken] public async Task<ActionResult> DisableTwoFactorAuthentication() { await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), false); var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); if (user != null) { await SignInAsync(user, isPersistent: false); } return RedirectToAction("Index", "Manage"); }
執行應用程式,並使用您先前註冊的帳戶登入。
按兩下您的使用者識別碼,以在
Index
控制器中啟動Manage
動作方法。
按兩下 [新增]。
AddPhoneNumber
動作方法會顯示對話方塊,以輸入可接收簡訊的電話號碼。// GET: /Account/AddPhoneNumber public ActionResult AddPhoneNumber() { return View(); }
在幾秒鐘內,您會收到包含驗證碼的簡訊。 輸入它,然後按 提交。
[管理] 檢視會顯示已新增您的電話號碼。
啟用雙因素驗證
在產生的範本應用程式中,您必須使用 UI 來啟用雙因素驗證 (2FA)。 若要啟用 2FA,請按兩下導覽列中的使用者識別碼(電子郵件別名)。
按兩下 [啟用 2FA]。
註銷,然後重新登入。 如果您已啟用電子郵件(請參閱我的 上一個教學課程),您可以選取 2FA 的 SMS 或電子郵件。
[驗證代碼] 頁面隨即顯示,您可以在其中輸入代碼(從簡訊或電子郵件)。
單擊 [記住此瀏覽器] 複選框,即可在使用這個瀏覽器和裝置時,無需使用 2FA 登入。 只要惡意使用者無法存取您的裝置,啟用 2FA 並點擊 記住此瀏覽器 會為您提供方便的一步驟密碼存取,同時仍保留對於所有來自非信任裝置的強大的2FA保護。 您可以在您經常使用的任何私人裝置上執行此動作。
本教學課程提供在新的 ASP.NET MVC 應用程式上啟用 2FA 的快速簡介。 我的教學課程 使用 SMS 和電子郵件搭配 ASP.NET 身分識別的雙因素驗證, 會詳細說明範例背後的程序代碼。
其他資源
- 使用 SMS 和電子郵件搭配 ASP.NET 身分識別的雙因素驗證 雙因素驗證 詳細說明雙因素驗證
- ASP.NET 身分識別建議資源的連結
- 使用 ASP.NET 身分識別進行帳戶確認和密碼復原 深入瞭解密碼復原和帳戶確認。
- ``` MVC 5 應用程式與 Facebook、Twitter、LinkedIn 和 Google OAuth 2 登入 本教學課程說明如何使用 Facebook 和 Google 的 OAuth 2 授權來撰寫 ASP.NET MVC 5 應用程式。 ``` 它也會示範如何將其他數據新增至身分識別資料庫。
- 將具有成員資格、OAuth 和 SQL Database 的安全 ASP.NET MVC 應用程式部署至 Azure Web。 本教學課程會新增 Azure 部署、如何使用角色保護應用程式、如何使用成員資格 API 來新增使用者和角色,以及其他安全性功能。
- 建立適用於 OAuth 2 的 Google 應用程式,並將應用程式連線至專案
- 在 Facebook 中建立應用程式並將應用程式連線至專案
- 在專案 中設定 SSL
- 如何設定 C# 和 ASP.NET MVC 開發環境