인증: SMS를 이용한 2단계 인증

등록일시: 2017-03-13 08:00,  수정일시: 2017-08-24 14:42
조회수: 4,868
이 문서는 ASP.NET Core 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.
본문에서는 SMS를 이용한 2단계 인증(2FA, Two-Factor Authentication)의 설정 방법을 살펴봅니다.

본문에서는 SMS를 이용한 2단계 인증(2FA, Two-Factor Authentication)의 설정 방법을 살펴봅니다. 그리고 본문의 예제에서는 SMS 공급자로 ASPSMS 서비스를 사용하지만 다른 SMS 공급자를 사용해도 무방합니다. 본 자습서를 살펴보기 전에 먼저 계정 확인 및 비밀번호 복구 자습서부터 완료하는 것을 권해드립니다.

새로운 ASP.NET Core 프로젝트 생성하기

개별 사용자 계정(Individual User Accounts) 옵션이 선택된 새로운 ASP.NET Core 웹 응용 프로그램을 생성합니다.

프로젝트를 생성한 다음에는 계정 확인 및 비밀번호 복구 자습서의 지시에 따라서 프로젝트를 설정하고 SSL을 필수로 사용하도록 구성합니다.

ASPSMS 서비스로 2단계 인증을 위한 SMS 구성하기

  • ASPSMS 계정을 생성합니다.

  • 무료 테스트 SMS 볼륨을 신정한 후, Userkey 메뉴에서 Userkey 정보와 여러분이 직접 지정했던 비밀번호를 따로 기억해 놓습니다. 이 값들은 이후 단계에서 Secret-Manager 도구를 통해서 관리될 것입니다.

  • Unlock Originators 메뉴에서 하나 이상의 발신자(Originators)를 잠금 해제 하거나 영문숫자 발신자(모든 네트워크에서 지원되지는 않습니다)를 선택합니다. 이 값 역시 이후 단계에서 Secret-Manager 도구를 통해서 관리될 것입니다.

  • ASPSMS NuGet 패키지를 설치합니다. 패키지 관리자 콘솔(Package Manager Console)에 다음 명령어를 입력합니다:

    Install-Package ASPSMS
  • 다음과 같이 Services/MessageServices.cs 파일에 코드를 추가해서 SMS를 활성화시킵니다.

public class AuthMessageSender : IEmailSender, ISmsSender
{
    public AuthMessageSender(IOptions<AuthMessageSMSSenderOptions> optionsAccessor)
    {
        Options = optionsAccessor.Value;
    }

    public AuthMessageSMSSenderOptions Options { get; }  // set only via Secret Manager

    public Task SendEmailAsync(string email, string subject, string message)
    {
        // Plug in your email service here to send an email.
        return Task.FromResult(0);
    }

    public Task SendSmsAsync(string number, string message)
    {
        // Plug in your SMS service here to send a text message.
        ASPSMS.SMS SMSSender = new ASPSMS.SMS();

        SMSSender.Userkey = Options.Userkey;
        SMSSender.Password = Options.Password;
        SMSSender.Originator = Options.Originator;

        SMSSender.AddRecipient(number);
        SMSSender.MessageData = message;

        SMSSender.SendTextSMS();

        return Task.FromResult(0);
    }
}
역주

이 예제 코드를 빌드하려면 먼저 다음 절에 설명하는 AuthMessageSMSSenderOptions 클래스까지 생성해야 합니다.

노트

SMS 메시지를 수신할 수 없는 상황인 경우, System.Diagnostics.Debug.WriteLine(message); 라인에 지정된 // 라인 주석 문자를 제거해서 응용 프로그램을 테스트 할 수 있습니다. 그러나 내장 로깅 시스템(Logging System)을 활용하는 방식을 더 권장합니다.

역주

실제로 본문의 예제 코드에는 System.Diagnostics.Debug.WriteLine(message);라는 라인이 존재하지 않습니다. 필요한 경우 그냥 이 코드를 추가하기만 하면 되는데, 용도는 테스트에 사용할 수 있는 SMS 공급자가 없을 경우, 출력 창에 표시되는 메시지 내용을 참고하여 SMS를 수신했다는 가정 하에 테스트를 진행하라는 의미입니다.

SMS 공급자의 key/value 구성하기

본문에서는 Options 패턴을 사용해서 사용자 계정 및 키 설정에 접근합니다. 자세한 정보는 ASP.NET Core 구성하기 문서를 참고하시기 바랍니다.

  • 보안 SMS 키를 가져오기 위한 클래스를 생성합니다. 이번 예제에서는 Services/AuthMessageSMSSenderOptions.cs 라는 파일로 AuthMessageSMSSenderOptions라는 클래스를 생성하겠습니다.
public class AuthMessageSMSSenderOptions
{
    public string Userkey { get; set; }
    public string Password { get; set; }
    public string Originator { get; set; }
}

그리고 다음과 같은 명령을 이용해서 Secret-Manager 도구를 사용해서 Userkey 정보와 Password 정보 및 Originator 정보를 설정합니다:

C:/WebSMS/src/WebApp1>dotnet user-secrets set Userkey IT2VHGB23K3
info: Successfully saved Userkey = IT2VHGB23K3 to the secret store.

AuthMessageSMSSenderOptions를 사용하도록 Startup 클래스 구성하기

Startup.cs 파일에 정의된 ConfigureServices 메서드의 끝 부분에 다음의 코드를 추가하여 AuthMessageSMSSenderOptions를 서비스 컨테이너에 추가합니다:

    // Register application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
    services.Configure<AuthMessageSMSSenderOptions>(Configuration);
}

2단계 인증 활성화시키기

  • Views/Manage/Index.cshtml Razor 뷰 파일을 엽니다.

  • 다음과 같은 문구로 시작하는 전화번호 마크업의 주석을 제거합니다.

    @*@(Model.PhoneNumber ?? "None")

  • 다음과 같은 문구로 시작하는 Model.TwoFactor 마크업의 주석을 제거합니다.

    @*@if (Model.TwoFactor)

  • <p>There are no two-factor authentication providers configured.로 시작하는 마크업을 제거하거나 주석으로 처리합니다.

    모든 작업을 마친 코드는 다음과 같습니다:

<dt>Phone Number:</dt>
<dd>
    <p>
        Phone Numbers can used as a second factor of verification in two-factor authentication.
        See <a href="http://go.microsoft.com/fwlink/?LinkID=532713">this article</a>
        for details on setting up this ASP.NET application to support two-factor authentication using SMS.
    </p>
    @(Model.PhoneNumber ?? "None") [
        @if (Model.PhoneNumber != null)
        {
            <a asp-controller="Manage" asp-action="AddPhoneNumber">Change</a>
                @: &nbsp;|&nbsp;
                <a asp-controller="Manage" asp-action="RemovePhoneNumber">Remove</a>
        }
        else
        {
            <a asp-controller="Manage" asp-action="AddPhoneNumber">Add</a>
        }
        ]
</dd>

<dt>Two-Factor Authentication:</dt>
<dd>
    @*<p>
        There are no two-factor authentication providers configured. See <a href="http://go.microsoft.com/fwlink/?LinkID=532713">this article</a>
        for setting up this application to support two-factor authentication.
    </p>*@
    @if (Model.TwoFactor)
        {
            <form asp-controller="Manage" asp-action="DisableTwoFactorAuthentication" method="post" class="form-horizontal" role="form">
                <text>
                    Enabled
                    <button type="submit" class="btn btn-link">Disable</button>
                </text>
            </form>
        }
        else
        {
            <form asp-controller="Manage" asp-action="EnableTwoFactorAuthentication" method="post" class="form-horizontal" role="form">
                <text>
                    Disabled
                    <button type="submit" class="btn btn-link">Enable</button>
                </text>
            </form>
        }
</dd>

2단계 인증으로 로그인하기

  • 응용 프로그램을 실행하고 새로운 사용자를 추가해서 로그인합니다.

  • 페이지 우측 상단의 사용자 이름을 클릭하면 Manage 컨트롤러의 Index 액션 메서드의 페이지로 이동합니다. Phone Number 항목의 Add 링크를 클릭합니다.

  • 인증 코드를 받을 전화번호를 추가하고 Send verification code 버튼을 클릭합니다.

  • 그러면 인증 코드가 담긴 문자 메시지가 전송될 것입니다. 전달 받은 인증 코드를 입력하고 Submit 버튼을 클릭합니다.

만약 문자 메시지를 받지 못했다면 ASPSMS 발신로그 절을 참고하시기 바랍니다.

  • Manage 뷰에 정상적으로 추가된 전화번호가 나타납니다.

  • Two-Factor Authentication 항목의 Enable 링크를 클릭해서 2단계 인증을 활성화시킵니다.

2단계 인증 테스트하기

  • 로그아웃합니다.

  • 로그인합니다.

  • 로그인 할 계정의 2단계 인증이 활성화되었으므로, 두 번째 인증 단계를 수행해야만 정상적으로 로그인할 수 있습니다. 본 자습서에서는 SMS 문자 인증을 활성화시키는 방법을 살펴보고 있지만, 본문의 예제 프로젝트에 사용된 내장 템플릿은 2단계 인증 방식을 이메일로 설정하는 방법도 지원합니다. 두 번째 인증 단계로 QR 코드 같은 추가적인 방법을 설정할 수도 있습니다. Submit 버튼을 클릭합니다.

  • SMS 메시지로 전달 받은 코드를 입력합니다.

  • 이때 Remember this browser 체크 박스를 선택하면, 이후 동일한 장치 및 브라우저로 로그인 할 때 2단계 인증 과정을 생략할 수 있습니다. 이처럼 2단계 인증을 활성화시키고 Remember this browser 체크 박스를 활용하면, 사용자의 계정에 접근하려고 시도하는 악의적인 사용자에 대한 강력한 2단계 보호를 제공할 수 있습니다 (악의적인 사용자가 사용자의 장치 자체에 접근하지 않는 한). 사용자는 자주 사용하는 모든 개인 장치에 이 설정을 적용할 수 있습니다. Remember this browser 체크 박스의 기능을 활용하면, 가끔 사용하는 장치에서는 2단계 인증을 통해 보안을 강화할 수 있고, 빈번하게 사용하는 장치에서는 2단계 인증의 번거로움을 간편하게 피할 수 있습니다.

무차별 대입 공격(Brute Force Attacks)을 방어하기 위한 계정 잠금 기능

2단계 인증을 사용할 때는 계정 잠금 기능을 함께 사용하는 것이 좋습니다. 그러면 사용자가 로그인에 실패할 때마다 (로컬 계정이든 소셜 계정이든) 실패한 2단계 인증 횟수가 저장되는데, 최대 횟수에 (기본값 5회) 도달하면 해당 사용자 계정이 5분간 잠깁니다 (DefaultAccountLockoutTimeSpan 옵션을 설정해서 잠금 시간을 지정할 수도 있습니다). 다음 구성은 로그인 시도가 10번 실패할 경우, 10분 동안 계정이 잠기도록 설정합니다.

    services.Configure<IdentityOptions>(options =>
    {
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
        options.Lockout.MaxFailedAccessAttempts = 10;
    });

    // Register application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
    services.Configure<AuthMessageSMSSenderOptions>(Configuration);
}
역주

계정 잠금 기능이 동작하지 않는다면 AccountController[HttpPost] Login 액션에서 PasswordSignInAsync 메서드를 호출하는 코드를 찾습니다. 그리고 lockoutOnFailure 매개변수에 전달되는 값을 true로 변경하면 됩니다.

ASPSMS 발신로그

만약 SMS 메시지가 전송되지 않는다면 ASPSMS 사이트에 로그인해서 Sendlog 메뉴를 살펴봅니다. 이 메뉴를 사용해서 메시지가 정상적으로 보내지고 전달됐는지 확인할 수 있습니다.