创建具有 SMS 双因素身份验证功能的 ASP.NET Web 窗体应用 (C#)

作者 :Erik Reitan

下载具有Email和短信Two-Factor身份验证的 ASP.NET Web Forms 应用

本教程介绍如何使用 Two-Factor 身份验证生成 ASP.NET Web Forms应用。 本教程旨在补充标题为创建具有用户注册、电子邮件确认和密码重置的安全 ASP.NET Web Forms应用的教程。 此外,本教程基于 Rick Anderson 的 MVC 教程

简介

本教程指导你完成使用 Visual Studio 创建支持Two-Factor身份验证的 ASP.NET Web Forms 应用程序所需的步骤。 Two-Factor身份验证是一个额外的用户身份验证步骤。 此额外步骤会在登录期间生成唯一的个人标识号 (PIN) 。 PIN 通常以电子邮件或短信的形式发送给用户。 然后,应用的用户在登录时输入 PIN 作为额外的身份验证措施。

教程任务和信息:

创建 ASP.NET Web Forms应用

首先安装和运行 Visual Studio Express 2013 for WebVisual Studio 2013同时安装 Visual Studio 2013 Update 3 或更高版本。 此外,还需要创建 一个 Twilio 帐户,如下所述。

注意

重要提示:必须安装 Visual Studio 2013 Update 3 或更高版本才能完成本教程。

  1. (文件 ->新建项目) 创建新项目,然后从“新建项目”对话框中选择 ASP.NET Web 应用程序模板以及.NET Framework版本 4.5.2。
  2. 从“新建 ASP.NET 项目”对话框中,选择Web Forms模板。 将默认身份验证保留为 “个人用户帐户”。 然后,单击“ 确定 ”创建新项目。
    “新建 A S P 点 Net 项目”对话框的屏幕截图,其中Web Forms图标以蓝色突出显示。
  3. 为项目启用安全套接字层 (SSL) 。 按照使用 Web Forms 教程系列入门Project 启用 SSL 部分中提供的步骤进行操作。
  4. 在 Visual Studio 中,打开 包管理器控制台 (工具 ->NuGet 包管理器 ->包管理器控制台) ,然后输入以下命令:
    Install-Package Twilio

设置短信和Two-Factor身份验证

本教程使用 Twilio,但你可以使用任何 SMS 提供程序。

  1. 创建 Twilio 帐户。

  2. 从 Twilio 帐户的“ 仪表板 ”选项卡中,复制 “帐户 SID ”和 “身份验证令牌”。 稍后将将它们添加到应用。

  3. 从“ 号码 ”选项卡中,复制 Twilio 电话号码

  4. 使 Twilio 帐户 SID身份验证令牌电话号码 可供应用使用。 为简单起见,请将这些值存储在 web.config 文件中。 部署到 Azure 时,可以安全地将值存储在网站的“配置”选项卡上的 “appSettings ”部分中。此外,在添加电话号码时,仅使用号码。
    请注意,还可以添加 SendGrid 凭据。 SendGrid 是一种电子邮件通知服务。 有关如何启用 SendGrid 的详细信息,请参阅标题为使用用户注册、电子邮件确认和密码重置创建安全 ASP.NET Web Forms应用教程的“挂钩 SendGrid”部分。

    </connectionStrings>
      <appSettings>
        <!-- SendGrid Credentials-->    
        <add key="emailServiceUserName" value="[EmailServiceAccountUserName]" />
        <add key="emailServicePassword" value="[EmailServiceAccountPassword]" />
        <!-- Twilio Credentials-->
        <add key="SMSSID" value="[SMSServiceAccountSID]" />
        <add key="SMSAuthToken" value="[SMSServiceAuthorizationToken]" />
        <add key="SMSPhoneNumber" value="+[SMSPhoneNumber]" />    
      </appSettings>
      <system.web>
    

    警告

    安全性 - 切勿将敏感数据存储在源代码中。 在此示例中,帐户和凭据存储在 Web.config 文件的 appSettings 部分中。 在 Azure 上,可以安全地将这些值存储在Azure 门户的“配置”选项卡上。 有关相关信息,请参阅 Rick Anderson 主题标题 为将密码和其他敏感数据部署到 ASP.NET 和 Azure 的最佳做法

  5. SmsService通过以黄色突出显示以下更改,在 App_Start\IdentityConfig.cs 文件中配置 类:

    public class SmsService : IIdentityMessageService
    {
        public Task SendAsync(IdentityMessage message)
        {
            var Twilio = new TwilioRestClient(
               ConfigurationManager.AppSettings["SMSSID"],
               ConfigurationManager.AppSettings["SMSAuthToken"]
            );
            var result = Twilio.SendMessage(
                ConfigurationManager.AppSettings["SMSPhoneNumber"],
               message.Destination, message.Body);
    
            // Status is one of Queued, Sending, Sent, Failed or null if the number is not valid
            Trace.TraceInformation(result.Status);
    
            // Twilio doesn't currently have an async API, so return success.
            return Task.FromResult(0);
        }
    }
    
  6. 将以下 using 语句添加到 IdentityConfig.cs 文件的开头:

    using Twilio;
    using System.Net;
    using System.Configuration;
    using System.Diagnostics;
    
  7. 通过删除以黄色突出显示的行来更新 Account/Manage.aspx 文件:

    <%@ Page Title="Manage Account" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Manage.aspx.cs" Inherits="WebFormsTwoFactor.Account.Manage" %>
    
    <%@ Register Src="~/Account/OpenAuthProviders.ascx" TagPrefix="uc" TagName="OpenAuthProviders" %>
    
    <asp:Content ContentPlaceHolderID="MainContent" runat="server">
        <h2><%: Title %>.</h2>
    
        <div>
            <asp:PlaceHolder runat="server" ID="successMessage" Visible="false" ViewStateMode="Disabled">
                <p class="text-success"><%: SuccessMessage %></p>
            </asp:PlaceHolder>
        </div>
    
        <div class="row">
            <div class="col-md-12">
                <div class="form-horizontal">
                    <h4>Change your account settings</h4>
                    <hr />
                    <dl class="dl-horizontal">
                        <dt>Password:</dt>
                        <dd>
                            <asp:HyperLink NavigateUrl="/Account/ManagePassword" Text="[Change]" Visible="false" ID="ChangePassword" runat="server" />
                            <asp:HyperLink NavigateUrl="/Account/ManagePassword" Text="[Create]" Visible="false" ID="CreatePassword" runat="server" />
                        </dd>
                        <dt>External Logins:</dt>
                        <dd><%: LoginsCount %>
                            <asp:HyperLink NavigateUrl="/Account/ManageLogins" Text="[Manage]" runat="server" />
    
                        </dd>
                        <%--
                            Phone Numbers can used as a second factor of verification in a two-factor authentication system.
                            See <a href="https://go.microsoft.com/fwlink/?LinkId=313242">this article</a>
                            for details on setting up this ASP.NET application to support two-factor authentication using SMS.
                            Uncomment the following block after you have set up two-factor authentication
                        --%>
    
                        <dt>Phone Number:</dt>
                        <%--
                        <% if (HasPhoneNumber)
                           { %>
                        <dd>
                            <asp:HyperLink NavigateUrl="/Account/AddPhoneNumber" runat="server" Text="[Add]" />
                        </dd>
                        <% }
                           else
                           { %>
                        <dd>
                            <asp:Label Text="" ID="PhoneNumber" runat="server" />
                            <asp:HyperLink NavigateUrl="/Account/AddPhoneNumber" runat="server" Text="[Change]" /> &nbsp;|&nbsp;
                            <asp:LinkButton Text="[Remove]" OnClick="RemovePhone_Click" runat="server" />
                        </dd>
                        <% } %>
                        --%>
    
                        <dt>Two-Factor Authentication:</dt>
                        <dd>
                            <p>
                                There are no two-factor authentication providers configured. See <a href="https://go.microsoft.com/fwlink/?LinkId=313242">this article</a>
                                for details on setting up this ASP.NET application to support two-factor authentication.
                            </p>
                            <% if (TwoFactorEnabled)
                              { %> 
                            <%--
                            Enabled
                            <asp:LinkButton Text="[Disable]" runat="server" CommandArgument="false" OnClick="TwoFactorDisable_Click" />
                            --%>
                            <% }
                              else
                              { %> 
                            <%--
                            Disabled
                            <asp:LinkButton Text="[Enable]" CommandArgument="true" OnClick="TwoFactorEnable_Click" runat="server" />
                            --%>
                            <% } %>
                        </dd>
                    </dl>
                </div>
            </div>
        </div>
    </asp:Content>
    
  8. Page_LoadManage.aspx.cs 代码隐藏的处理程序中,取消注释以黄色突出显示的代码行,使其如下所示:

    protected void Page_Load()
    {
        var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
    
        HasPhoneNumber = String.IsNullOrEmpty(manager.GetPhoneNumber(User.Identity.GetUserId()));
    
        // Enable this after setting up two-factor authentientication
        PhoneNumber.Text = manager.GetPhoneNumber(User.Identity.GetUserId()) ?? String.Empty;
    
        TwoFactorEnabled = manager.GetTwoFactorEnabled(User.Identity.GetUserId());
    
        LoginsCount = manager.GetLogins(User.Identity.GetUserId()).Count;
    
        var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
    
        if (!IsPostBack)
        {
            // Determine the sections to render
            if (HasPassword(manager))
            {
                ChangePassword.Visible = true;
            }
            else
            {
                CreatePassword.Visible = true;
                ChangePassword.Visible = false;
            }
    
            // Render success message
            var message = Request.QueryString["m"];
            if (message != null)
            {
                // Strip the query string from action
                Form.Action = ResolveUrl("~/Account/Manage");
    
                SuccessMessage =
                    message == "ChangePwdSuccess" ? "Your password has been changed."
                    : message == "SetPwdSuccess" ? "Your password has been set."
                    : message == "RemoveLoginSuccess" ? "The account was removed."
                    : message == "AddPhoneNumberSuccess" ? "Phone number has been added"
                    : message == "RemovePhoneNumberSuccess" ? "Phone number was removed"
                    : String.Empty;
                successMessage.Visible = !String.IsNullOrEmpty(SuccessMessage);
            }
        }
    }
    
  9. Account/TwoFactorAuthenticationSignIn.aspx.cs 的代码隐藏中,通过添加以下以黄色突出显示的代码来更新 Page_Load 处理程序:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            var userId = signinManager.GetVerifiedUserId<ApplicationUser, string>();
            if (userId == null)
            {
                Response.Redirect("/Account/Error", true);
            }
            var userFactors = manager.GetValidTwoFactorProviders(userId);
            Providers.DataSource = userFactors.Select(x => x).ToList();
            Providers.DataBind();
        }
    }
    

    通过更改上述代码,包含身份验证选项的“Providers”DropDownList 将不会重置为第一个值。 这将允许用户成功选择身份验证时要使用的所有选项,而不仅仅是第一个选项。

  10. “解决方案资源管理器”中,右键单击“Default.aspx”,然后选择“设为起始页”。

  11. 通过测试应用,首先 (Ctrl+Shift+B) 生成应用,然后 (F5) 运行应用,然后选择 “注册 ”以创建新用户帐户,或者选择“ 登录 ”(如果用户帐户已注册)。

  12. (用户) 登录后,单击导航栏中的“用户 ID” (电子邮件地址) 以显示“ 管理帐户 ”页 (Manage.aspx) 。
    A S P dot Net 响应浏览器窗口的屏幕截图,其中突出显示了带有红色矩形的用户 ID。

  13. “管理帐户”页上,单击“电话号码”旁边的“添加”。
    “管理帐户”浏览器窗口的屏幕截图,其中显示了帐户设置的列表以及用于更改这些设置的选项链接。

  14. 添加用户 () 希望接收短信 (短信) 的电话号码,然后单击“ 提交 ”按钮。
    “电话号码”浏览器窗口的屏幕截图,其中显示了“电话号码”字段,其中包含输入的电话号码值和“提交”按钮。
    此时,应用将使用 Web.config 凭据联系 Twilio。 短信 (短信) 将发送到与用户帐户关联的手机。 可以通过查看 Twilio 仪表板来验证 Twilio 消息是否已发送。

  15. 几秒钟后,与用户帐户关联的手机将收到一条包含验证码的短信。 输入验证码并按 “提交”。
    “验证电话号码”浏览器窗口的屏幕截图,其中显示了“代码”字段,其中包含输入的验证码和“提交”按钮。

为注册用户启用Two-Factor身份验证

此时,你已为应用启用了双因素身份验证。 对于使用双重身份验证的用户,他们只需使用 UI 更改其设置。

  1. 作为应用用户,你可以通过单击导航栏中的用户 ID (电子邮件别名) 来为特定帐户启用双重身份验证,以显示 “管理帐户” 页面。然后,单击 “启用” 链接,为帐户启用双重身份验证。“管理帐户”浏览器窗口的屏幕截图,其中以红色突出显示了“启用与Two-Factor身份验证关联的链接”。
  2. 注销,然后重新登录。 如果已启用电子邮件,可以选择短信或电子邮件进行双重身份验证。 如果尚未启用电子邮件,请参阅标题为使用用户注册创建安全 ASP.NET Web Forms应用Email确认和密码重置的教程。Two-Factor身份验证浏览器窗口的屏幕截图,其中显示了“选择Two-Factor身份验证提供程序”下拉列表。
  3. 将显示“Two-Factor身份验证”页,可在其中输入短信或电子邮件) (代码。Two-Factor身份验证浏览器窗口的屏幕截图,其中显示了“代码”字段,其中包含输入的验证码和“提交”按钮。
    单击“记住此浏览器检查”框将免除在使用选中该框的浏览器和设备时使用双重身份验证登录的需要。 只要恶意用户无法访问你的设备,启用双因素身份验证并单击“ 记住此浏览器 ”即可为你提供方便的一步密码访问,同时仍保留对来自不受信任设备的所有访问的强双因素身份验证保护。 可以在经常使用的任何专用设备上进行此操作。

其他资源