다음을 통해 공유


SMS 2단계 인증을 사용하는 ASP.NET Web Forms 앱 만들기(C#)

작성자 : Erik Reitan

Email 및 SMS 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은 일반적으로 사용자에게 이메일 또는 SMS 메시지로 전송됩니다. 그러면 앱 사용자가 로그인할 때 추가 인증 측정값으로 PIN을 입력합니다.

자습서 작업 및 정보:

ASP.NET Web Forms 앱 만들기

먼저 웹 또는Visual Studio 2013 Visual Studio Express 2013을 설치하고 실행합니다. Visual Studio 2013 업데이트 3 이상을 설치합니다. 또한 아래에 설명된 대로 Twilio 계정을 만들어야 합니다.

참고

중요: 이 자습서를 완료하려면 Visual Studio 2013 업데이트 3 이상을 설치해야 합니다.

  1. 새 프로젝트(파일 ->새 프로젝트)를 만들고 새 프로젝트 대화 상자에서 .NET Framework 버전 4.5.2와 함께 ASP.NET 웹 애플리케이션 템플릿을 선택합니다.
  2. 새 ASP.NET 프로젝트 대화 상자에서 Web Forms 템플릿을 선택합니다. 기본 인증은 개별 사용자 계정으로 둡니다. 그런 다음 확인을 클릭하여 새 프로젝트를 만듭니다.
    파란색으로 강조 표시된 Web Forms 아이콘을 보여 주는 새 ASP 점 Net 프로젝트 대화 상자의 스크린샷
  3. 프로젝트에 대해 SSL(Secure Sockets Layer)을 사용하도록 설정합니다. Web Forms 자습서 시리즈의 시작Project에 SSL 사용 섹션에서 사용할 수 있는 단계를 따릅니다.
  4. Visual Studio에서 패키지 관리자 콘솔 (도구 ->NuGet 패키지 관리자 ->패키지 관리자 콘솔)을 열고 다음 명령을 입력합니다.
    Install-Package Twilio

SMS 및 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 앱 만들기 자습서의 'Hook Up 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 Portal 구성 탭에 안전하게 저장할 수 있습니다. 관련 정보는 ASP.NET 및 Azure에 암호 및 기타 중요한 데이터를 배포하기 위한 모범 사례라는 Rick Anderson의 항목을 참조하세요.

  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. IdentityConfig.cs 파일의 시작 부분에 다음 using 문을 추가합니다.

    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의 codebehind에서 노란색으로 강조 표시된 다음 코드를 추가하여 처리기를 업데이트 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();
        }
    }
    

    위의 코드를 변경하면 인증 옵션을 포함하는 "공급자" DropDownList가 첫 번째 값으로 다시 설정되지 않습니다. 이렇게 하면 사용자가 첫 번째 옵션뿐만 아니라 인증할 때 사용할 모든 옵션을 성공적으로 선택할 수 있습니다.

  10. 솔루션 탐색기Default.aspx를 마우스 오른쪽 단추로 클릭하고 시작 페이지로 설정을 선택합니다.

  11. 앱을 테스트하여 먼저 앱을 빌드한 다음(Ctrl+Shift+B) 앱(F5)을 실행하고 등록 을 선택하여 새 사용자 계정을 만들거나 사용자 계정이 이미 등록된 경우 로그인 을 선택합니다.

  12. 사용자로 로그인하면 탐색 모음에서 사용자 ID(전자 메일 주소)를 클릭하여 계정 관리 페이지(Manage.aspx)를 표시합니다.
    빨간색 사각형으로 강조 표시된 사용자 ID를 보여 주는 A SP dot Net 응답 브라우저 창의 스크린샷.

  13. 계정 관리 페이지에서 전화 번호 옆에 있는 추가를 클릭합니다.
    계정 설정 목록과 이를 변경하는 옵션 링크를 보여 주는 계정 관리 브라우저 창의 스크린샷.

  14. 사용자로서 SMS 메시지(문자 메시지)를 받을 전화 번호를 추가하고 제출 단추를 클릭합니다.
    입력한 전화 번호 값과 제출 단추가 있는 전화 번호 필드를 보여 주는 전화 번호 브라우저 창의 스크린샷
    이 시점에서 앱은 Web.config 자격 증명을 사용하여 Twilio에 연결합니다. SMS 메시지(문자 메시지)는 사용자 계정과 연결된 휴대폰으로 전송됩니다. Twilio dashboard 확인하여 Twilio 메시지가 전송되었는지 확인할 수 있습니다.

  15. 몇 초 후에 사용자 계정과 연결된 휴대폰에 확인 코드가 포함된 문자 메시지가 표시됩니다. 확인 코드를 입력하고 제출을 누릅니 .
    입력한 확인 코드와 제출 단추가 있는 코드 필드를 보여 주는 전화 번호 확인 브라우저 창의 스크린샷.

등록된 사용자에 대해 Two-Factor 인증 사용

이 시점에서 앱에 대해 2단계 인증을 사용하도록 설정했습니다. 사용자가 2단계 인증을 사용하려면 UI를 사용하여 설정을 변경하기만 하면 됩니다.

  1. 앱의 사용자는 탐색 모음에서 사용자 ID(이메일 별칭)를 클릭하여 계정 관리 페이지를 표시하여 특정 계정에 대해 2단계 인증을 사용하도록 설정할 수 있습니다. 그런 다음 사용 링크를 클릭하여 계정에 대해 2단계 인증을 사용하도록 설정합니다. 빨간색으로 강조 표시된 Two-Factor 인증과 연결된 사용 링크를 보여 주는 계정 관리 브라우저 창의 스크린샷
  2. 로그오프한 다음 다시 로그인합니다. 전자 메일을 사용하도록 설정한 경우 2단계 인증을 위해 SMS 또는 전자 메일을 선택할 수 있습니다. 전자 메일을 사용하도록 설정하지 않은 경우 사용자 등록을 사용하여 보안 ASP.NET Web Forms 앱 만들기, 확인 및 암호 재설정 Email 자습서를 참조하세요. Two-Factor 인증 공급자 선택 드롭다운 목록을 보여 주는 Two-Factor 인증 브라우저 창의 스크린샷
  3. SMS 또는 전자 메일에서 코드를 입력할 수 있는 Two-Factor 인증 페이지가 표시됩니다. 입력한 확인 코드와 제출 단추가 있는 코드 필드를 보여 주는 Two-Factor 인증 브라우저 창의 스크린샷
    이 브라우저 검사 저장 상자를 클릭하면 확인란을 선택한 브라우저 및 디바이스를 사용할 때 2단계 인증을 사용하여 로그인할 필요가 없습니다. 악의적인 사용자가 디바이스에 액세스할 수 없는 한 2단계 인증을 사용하도록 설정하고 이 브라우저 저장을 클릭하면 편리한 1단계 암호 액세스가 제공되고 신뢰할 수 없는 디바이스의 모든 액세스에 대해 강력한 2단계 인증 보호가 유지됩니다. 정기적으로 사용하는 모든 프라이빗 디바이스에서 이 작업을 수행할 수 있습니다.

추가 리소스