SMS 및 전자 메일 2단계 인증을 사용하는 ASP.NET MVC 5 앱

작성자 : Rick Anderson

이 자습서에서는 Two-Factor 인증을 사용하여 ASP.NET MVC 5 웹앱을 빌드하는 방법을 보여줍니다. 계속하기 전에 로그인, 전자 메일 확인 및 암호 재설정을 사용하여 보안 ASP.NET MVC 5 웹앱 만들기 를 완료해야 합니다. 완료된 애플리케이션은 여기에서 다운로드할 수 있습니다. 다운로드에는 이메일 또는 SMS 공급자를 설정하지 않고 이메일 확인 및 SMS를 테스트할 수 있는 디버깅 도우미가 포함되어 있습니다.

이 자습서는 Rick Anderson (Twitter: @RickAndMSFT )이 작성했습니다.

ASP.NET MVC 앱 만들기

먼저 Visual Studio Express 2013 for Web 이상을 설치하고 실행합니다.

참고

경고: 계속하기 전에 로그인, 전자 메일 확인 및 암호 재설정을 사용하여 보안 ASP.NET MVC 5 웹앱 만들기 를 완료해야 합니다. 이 자습서를 완료하려면 Visual Studio 2013 업데이트 3 이상을 설치해야 합니다.

  1. 새 ASP.NET 웹 프로젝트를 만들고 MVC 템플릿을 선택합니다. Web Forms ASP.NET ID도 지원하므로 웹 양식 앱에서 유사한 단계를 수행할 수 있습니다.
    새 ASP 점 NET 프로젝트 창을 보여 주는 스크린샷. 기본 인증인 개별 사용자 계정이 강조 표시됩니다.
  2. 기본 인증은 개별 사용자 계정으로 둡니다. Azure에서 앱을 호스트하려면 검사 확인란을 선택된 상태로 둡니다. 자습서의 뒷부분에서 Azure에 배포합니다. Azure 계정을 무료로 열 수 있습니다.
  3. SSL을 사용하도록 프로젝트를 설정합니다.

2단계 인증을 위한 SMS 설정

이 자습서에서는 Twilio 또는 ASPSMS를 사용하기 위한 지침을 제공하지만 다른 SMS 공급자를 사용할 수 있습니다.

  1. SMS 공급자를 사용하여 사용자 계정 만들기

    Twilio 또는 ASPSMS 계정을 만듭니다.

  2. 추가 패키지 설치 또는 서비스 참조 추가

    Twilio:
    패키지 관리자 콘솔에서 다음 명령을 입력합니다.
    Install-Package Twilio

    ASPSMS:
    다음 서비스 참조를 추가해야 합니다.

    서비스 참조 추가 창을 보여 주는 스크린샷 주소 및 네임스페이스 입력 막대가 강조 표시됩니다.

    주소:
    https://webservice.aspsms.com/aspsmsx2.asmx?WSDL

    네임스페이스:
    ASPSMSX2

  3. SMS 공급자 사용자 자격 증명 구성

    Twilio:
    Twilio 계정의 대시보드 탭에서 계정 SID인증 토큰을 복사합니다.

    ASPSMS:
    계정 설정에서 Userkey 로 이동하여 자체 정의 암호와 함께 복사 합니다.

    나중에 이러한 값을 키 "SMSAccountIdentification""SMSAccountPassword" 내의web.config 파일에 저장합니다.

  4. SenderID/Originator 지정

    Twilio:
    숫자 탭에서 Twilio 전화 번호를 복사합니다.

    ASPSMS:
    보낸 사람 잠금 해제 메뉴에서 하나 이상의 보낸 사람의 잠금을 해제하거나 영숫자 보낸 사람(모든 네트워크에서 지원되지 않음)을 선택합니다.

    나중에 키 내의 web.config 파일에 이 값을 저장합니다 "SMSAccountFrom" .

  5. SMS 공급자 자격 증명을 앱으로 전송

    앱에서 자격 증명 및 보낸 사람 전화 번호를 사용할 수 있도록 합니다. 작업을 간단하게 유지하기 위해 이러한 값을web.config 파일에 저장합니다. Azure에 배포할 때 웹 사이트 구성 탭의 앱 설정 섹션에 값을 안전하게 저장할 수 있습니다.

    </connectionStrings>
       <appSettings>
          <add key="webpages:Version" value="3.0.0.0" />
          <!-- Markup removed for clarity. -->
          <!-- SendGrid-->
          <add key="mailAccount" value="account" />
          <add key="mailPassword" value="password" />
          <add key="SMSAccountIdentification" value="My Identification" />
          <add key="SMSAccountPassword" value="My Password" />
          <add key="SMSAccountFrom" value="+12065551234" />
       </appSettings>
      <system.web>
    

    경고

    보안 - 소스 코드에 중요한 데이터를 저장하지 않습니다. 위의 코드에 계정 및 자격 증명이 추가되어 샘플을 단순하게 유지합니다. ASP.NET 및 Azure에 암호 및 기타 중요한 데이터를 배포하는 모범 사례를 참조하세요.

  6. SMS 공급자에 대한 데이터 전송 구현

    SmsServiceApp_Start\IdentityConfig.cs 파일에서 클래스를 구성합니다.

    사용된 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
        }
    }
    
  7. 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")
                @: &nbsp;|&nbsp;
                @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>
    
  8. EnableTwoFactorAuthenticationDisableTwoFactorAuthentication 작업 메서드에 [ValidateAntiForgeryToken] 특성이 있는지 확인 ManageController 합니다.

    //
    // 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");
    }
    
  9. 앱을 실행하고 이전에 등록한 계정으로 로그인합니다.

  10. 컨트롤러에서 작업 메서드를 활성화하는 사용자 ID를 IndexManage 클릭합니다.
    ASP dot NET 앱 홈페이지를 보여 주는 스크린샷. 샘플 사용자 ID가 강조 표시됩니다.

  11. 추가를 클릭합니다.
    ASP dot NET 앱 계정 설정 페이지를 보여 주는 스크린샷. 없음 전화 번호 섹션 옆에 추가가 강조 표시됩니다.

  12. 작업 메서드는 AddPhoneNumber SMS 메시지를 받을 수 있는 전화 번호를 입력하는 대화 상자를 표시합니다.

    // GET: /Account/AddPhoneNumber
    public ActionResult AddPhoneNumber()
    {
       return View();
    }
    

    ASP dot NET 앱 전화 번호 추가 페이지를 보여 주는 스크린샷. 샘플 전화 번호는 아래에 확인 코드 보내기 단추로 채워집니다.

  13. 몇 초 후에 확인 코드가 포함된 문자 메시지가 표시됩니다. 입력하고 제출을 누릅니다.
    샘플 확인 코드와 그 아래에 제출 단추로 채워진 입력 막대를 보여 주는 SP 점 NET 앱 전화 번호 추가 페이지의 스크린샷.

  14. 관리 보기에는 전화 번호가 추가된 것으로 표시됩니다.

2단계 인증 사용

템플릿 생성 앱에서 UI를 사용하여 2FA(2단계 인증)를 사용하도록 설정해야 합니다. 2FA를 사용하도록 설정하려면 탐색 모음에서 사용자 ID(이메일 별칭)를 클릭합니다.

ASP dot NET 앱 홈 페이지를 표시하는 스크린샷. 샘플 사용자 ID가 강조 표시됩니다.

2FA 사용을 클릭합니다.

ASP dot NET 앱 계정 설정 페이지를 보여 주는 스크린샷. Two-Factor 인증: 링크 사용 섹션이 강조 표시되어 있습니다.

로그아웃한 다음 다시 로그인합니다. 전자 메일을 사용하도록 설정한 경우( 이전 자습서 참조) 2FA에 대한 SMS 또는 이메일을 선택할 수 있습니다.

ASP dot NET 앱 확인 코드 보내기 페이지를 보여 주는 스크린샷. 전화 코드 및 Email 코드를 보여 주는 드롭다운 메뉴가 선택됩니다.

코드 확인 페이지는 SMS 또는 전자 메일에서 코드를 입력할 수 있는 위치에 표시됩니다.

2 FA에 대한 ASP 점 NET 앱 확인 페이지를 보여 주는 스크린샷. 샘플 코드 아래에 이 브라우저 기억 확인란이 강조 표시됩니다.

이 브라우저 검사 기억 상자를 클릭하면 확인란을 선택한 브라우저 및 디바이스를 사용할 때 2FA를 사용하여 로그인할 필요가 없습니다. 악의적인 사용자가 디바이스에 액세스할 수 없는 한, 2FA를 사용하도록 설정하고 이 브라우저 기억 을 클릭하면 신뢰할 수 없는 디바이스의 모든 액세스에 대해 강력한 2FA 보호를 유지하면서 편리한 1단계 암호 액세스를 제공합니다. 정기적으로 사용하는 모든 프라이빗 디바이스에서 이 작업을 수행할 수 있습니다.

이 자습서에서는 새 ASP.NET MVC 앱에서 2FA를 사용하도록 설정하는 방법을 간략하게 소개합니다. SMS를 사용하는 내 자습서 2단계 인증 및 ASP.NET ID가 있는 전자 메일은 샘플 뒤에 있는 코드에 대해 자세히 설명합니다.

추가 리소스