ASP.NET Core SMS를 사용 하는 2 단계 인증Two-factor authentication with SMS in ASP.NET Core

Rick Anderson스위스-개발자By Rick Anderson and Swiss-Devs

경고

시간 기반 일회용 암호 알고리즘 (TOTP)을 사용 하는 2 단계 인증 (2FA) authenticator 앱은 2FA의 업계 권장 방법입니다.Two factor authentication (2FA) authenticator apps, using a Time-based One-time Password Algorithm (TOTP), are the industry recommended approach for 2FA. 2FA는 TOTP를 사용 하 여 SMS 2FA에 선호 됩니다.2FA using TOTP is preferred to SMS 2FA. 자세한 내용은 ASP.NET Core ASP.NET Core 2.0 이상에 대해 TOTP authenticator 앱에 대 한 QR 코드 생성 사용 을 참조 하세요.For more information, see Enable QR Code generation for TOTP authenticator apps in ASP.NET Core for ASP.NET Core 2.0 and later.

이 자습서에서는 SMS를 사용 하 여 2 단계 인증 (2FA)을 설정 하는 방법을 보여 줍니다.This tutorial shows how to set up two-factor authentication (2FA) using SMS. 지침은 twilio 및 관련 sms에 제공 되지만 다른 sms 공급자를 사용할 수 있습니다.Instructions are given for twilio and ASPSMS, but you can use any other SMS provider. 이 자습서를 시작 하기 전에 계정 확인 및 암호 복구 를 완료 하는 것이 좋습니다.We recommend you complete Account Confirmation and Password Recovery before starting this tutorial.

샘플 코드 보기 또는 다운로드View or download sample code. 다운로드 방법How to download.

새 ASP.NET Core 프로젝트 만들기Create a new ASP.NET Core project

Web2FA개별 사용자 계정을 사용 하 여 라는 새 ASP.NET Core 웹 앱을 만듭니다.Create a new ASP.NET Core web app named Web2FA with individual user accounts. 의 지침에 따라 ASP.NET Core에서 HTTPS 적용 HTTPS를 설정 및 요구 합니다.Follow the instructions in ASP.NET Core에서 HTTPS 적용 to set up and require HTTPS.

SMS 계정 만들기Create an SMS account

SMS 계정 (예: twilio 또는 기타 sms)을 만듭니다.Create an SMS account, for example, from twilio or ASPSMS. 인증 자격 증명을 기록 합니다 (twilio: accountSid 및 authToken,: Userkey 및 Password 용).Record the authentication credentials (for twilio: accountSid and authToken, for ASPSMS: Userkey and Password).

SMS 공급자 자격 증명 파악Figuring out SMS Provider credentials

TwilioTwilio:

Twilio 계정의 대시보드 탭에서 계정 SID인증 토큰을 복사 합니다.From the Dashboard tab of your Twilio account, copy the Account SID and Auth token.

다음 SMS:ASPSMS:

계정 설정에서 Userkey 로 이동 하 여 암호와 함께 복사 합니다.From your account settings, navigate to Userkey and copy it together with your Password.

이러한 값은 나중에 키 및의 비밀 manager 도구를 사용 하 여에 저장 합니다 SMSAccountIdentification SMSAccountPassword .We will later store these values in with the secret-manager tool within the keys SMSAccountIdentification and SMSAccountPassword.

SenderID/송신자 지정Specifying SenderID / Originator

Twilio: 숫자 탭에서 Twilio 전화 번호를 복사 합니다.Twilio: From the Numbers tab, copy your Twilio phone number.

다음 sms: 보낸 사람 잠금 해제 메뉴 내에서 하나 이상의 발신자의 잠금을 해제 하거나 영숫자 송신자 (모든 네트워크에서 지원 되지 않음)를 선택 합니다.ASPSMS: Within the Unlock Originators Menu, unlock one or more Originators or choose an alphanumeric Originator (Not supported by all networks).

나중에이 값을 키 내의 비밀 관리자 도구와 함께 저장 SMSAccountFrom 합니다.We will later store this value with the secret-manager tool within the key SMSAccountFrom.

SMS 서비스에 대 한 자격 증명 제공Provide credentials for the SMS service

옵션 패턴 을 사용 하 여 사용자 계정 및 키 설정에 액세스 합니다.We'll use the Options pattern to access the user account and key settings.

  • 보안 SMS 키를 인출 하는 클래스를 만듭니다.Create a class to fetch the secure SMS key. 이 샘플의 경우 SMSoptions 클래스는 Services/smsoptions .cs 파일에서 만들어집니다.For this sample, the SMSoptions class is created in the Services/SMSoptions.cs file.
namespace Web2FA.Services
{
    public class SMSoptions
    {
        public string SMSAccountIdentification { get; set; }
        public string SMSAccountPassword { get; set; }
        public string SMSAccountFrom { get; set; }
    }
}

을 ( SMSAccountIdentificationSMSAccountPassword SMSAccountFrom ) 암호 관리자 도구를 사용 하 여 설정 합니다.Set the SMSAccountIdentification, SMSAccountPassword and SMSAccountFrom with the secret-manager tool. 다음은 그 예입니다. For example:

C:/Web2FA/src/WebApp1>dotnet user-secrets set SMSAccountIdentification 12345
info: Successfully saved SMSAccountIdentification = 12345 to the secret store.
  • SMS 공급자에 대 한 NuGet 패키지를 추가 합니다.Add the NuGet package for the SMS provider. 패키지 관리자 콘솔 (PMC)에서 다음을 실행 합니다.From the Package Manager Console (PMC) run:

TwilioTwilio:

Install-Package Twilio

다음 SMS:ASPSMS:

Install-Package ASPSMS

  • Service/MessageServices 파일에 코드를 추가 하 여 SMS를 사용 하도록 설정 합니다.Add code in the Services/MessageServices.cs file to enable SMS. Twilio 또는 다음 SMS 섹션을 사용 합니다.Use either the Twilio or the ASPSMS section:

TwilioTwilio:

using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

namespace Web2FA.Services
{
    // This class is used by the application to send Email and SMS
    // when you turn on two-factor authentication in ASP.NET Identity.
    // For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713
    public class AuthMessageSender : IEmailSender, ISmsSender
    {
        public AuthMessageSender(IOptions<SMSoptions> optionsAccessor)
        {
            Options = optionsAccessor.Value;
        }

        public SMSoptions 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.
            // Your Account SID from twilio.com/console
            var accountSid = Options.SMSAccountIdentification;
            // Your Auth Token from twilio.com/console
            var authToken = Options.SMSAccountPassword;

            TwilioClient.Init(accountSid, authToken);

            return MessageResource.CreateAsync(
              to: new PhoneNumber(number),
              from: new PhoneNumber(Options.SMSAccountFrom),
              body: message);
        }
    }
}

다음 SMS:ASPSMS:

using Microsoft.Extensions.Options;
using System.Threading.Tasks;

namespace Web2FA.Services
{
    // This class is used by the application to send Email and SMS
    // when you turn on two-factor authentication in ASP.NET Identity.
    // For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713
    public class AuthMessageSender : IEmailSender, ISmsSender
    {
        public AuthMessageSender(IOptions<SMSoptions> optionsAccessor)
        {
            Options = optionsAccessor.Value;
        }

        public SMSoptions 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)
        {
            ASPSMS.SMS SMSSender = new ASPSMS.SMS();

            SMSSender.Userkey = Options.SMSAccountIdentification;
            SMSSender.Password = Options.SMSAccountPassword;
            SMSSender.Originator = Options.SMSAccountFrom;

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

            SMSSender.SendTextSMS();

            return Task.FromResult(0);
        }
    }
}

사용할 시작 구성 SMSoptionsConfigure startup to use SMSoptions

SMSoptions ConfigureServices Startup.cs의 메서드에서 서비스 컨테이너에를 추가 합니다.Add SMSoptions to the service container in the ConfigureServices method in the Startup.cs:

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

2단계 인증 사용Enable two-factor authentication

Views/Manage/ Razor indexview 파일을 열고 주석 문자를 제거 합니다. 태그는 주석 처리 되지 않습니다.Open the Views/Manage/Index.cshtml Razor view file and remove the comment characters (so no markup is commented out).

2 단계 인증을 사용 하 여 로그인Log in with two-factor authentication

  • 앱을 실행 하 고 새 사용자를 등록 합니다.Run the app and register a new user

Microsoft Edge에서 열린 웹 응용 프로그램 등록 보기

  • 컨트롤러 관리에서 작업 메서드를 활성화 하는 사용자 이름을 누릅니다 Index .Tap on your user name, which activates the Index action method in Manage controller. 전화 번호 추가 링크를 탭 합니다.Then tap the phone number Add link.

뷰 관리-"추가" 링크를 누릅니다.

  • 확인 코드를 수신 하는 전화 번호를 추가 하 고 확인 코드 보내기를 탭 합니다.Add a phone number that will receive the verification code, and tap Send verification code.

전화 번호 추가 페이지

  • 확인 코드가 포함 된 문자 메시지를 받게 됩니다.You will get a text message with the verification code. 입력 하 고 제출 을 탭 합니다.Enter it and tap Submit

전화 번호 확인 페이지

문자 메시지를 얻지 못한 경우 twilio log 페이지를 참조 하세요.If you don't get a text message, see twilio log page.

  • 관리 보기에는 전화 번호가 성공적으로 추가 된 것이 표시 됩니다.The Manage view shows your phone number was added successfully.

보기 관리-전화 번호를 추가 했습니다.

  • 사용 을 탭 하 여 2 단계 인증을 사용 하도록 설정 합니다.Tap Enable to enable two-factor authentication.

보기 관리-2 단계 인증 사용

2 단계 인증 테스트Test two-factor authentication

  • 로그오프합니다.Log off.

  • 로그인합니다.Log in.

  • 사용자 계정에서 2 단계 인증을 사용 하도록 설정 했으므로 두 번째 인증 단계를 제공 해야 합니다.The user account has enabled two-factor authentication, so you have to provide the second factor of authentication . 이 자습서에서는 전화 확인을 사용 하도록 설정 했습니다.In this tutorial you have enabled phone verification. 기본 제공 템플릿을 사용 하 여 두 번째 단계로 전자 메일을 설정할 수도 있습니다.The built in templates also allow you to set up email as the second factor. QR 코드와 같은 인증을 위한 추가 두 번째 요소를 설정할 수 있습니다.You can set up additional second factors for authentication such as QR codes. 제출을 탭 합니다.Tap Submit.

확인 코드 보기 보내기

  • SMS 메시지에서 가져온 코드를 입력 합니다.Enter the code you get in the SMS message.

  • 이 브라우저 기억을 확인란을 클릭 하면 동일한 장치 및 브라우저를 사용할 때 로그온 하는 데 2fa를 사용할 필요가 없습니다.Clicking on the Remember this browser check box will exempt you from needing to use 2FA to log on when using the same device and browser. 2FA를 사용 하도록 설정 하 고 사용자가 장치에 액세스할 수 없는 경우 이 브라우저 를 사용 하도록 설정 하면 악의적인 사용자가 자신의 계정에 액세스 하는 데 사용 하는 강력한 2fa 보호 기능이 제공 됩니다.Enabling 2FA and clicking on Remember this browser will provide you with strong 2FA protection from malicious users trying to access your account, as long as they don't have access to your device. 정기적으로 사용 하는 모든 개인 장치에서이 작업을 수행할 수 있습니다.You can do this on any private device you regularly use. 이 브라우저 기억을설정 하면 정기적으로 사용 하지 않는 장치에서 2fa의 보안을 강화 하 고 사용자의 장치에 대해 2fa를 거치지 않아도 편리 하 게 활용할 수 있습니다.By setting Remember this browser, you get the added security of 2FA from devices you don't regularly use, and you get the convenience on not having to go through 2FA on your own devices.

확인 보기

무차별 암호 대입 공격 으로부터 보호 하기 위한 계정 잠금Account lockout for protecting against brute force attacks

계정 잠금은 2FA를 사용 하는 것이 좋습니다.Account lockout is recommended with 2FA. 사용자가 로컬 계정이 나 소셜 계정을 통해 로그인 하면 2FA에서 실패 한 각 시도가 저장 됩니다.Once a user signs in through a local account or social account, each failed attempt at 2FA is stored. 실패 한 최대 액세스 시도 횟수에 도달 하면 사용자가 잠깁니다 (기본값: 5 분의 액세스 시도 실패 후 5 분 잠금).If the maximum failed access attempts is reached, the user is locked out (default: 5 minute lockout after 5 failed access attempts). 성공적인 인증은 실패 한 액세스 시도 횟수를 다시 설정 하 고 시계를 다시 설정 합니다.A successful authentication resets the failed access attempts count and resets the clock. 최대 실패 한 액세스 시도 및 잠금 시간은 Maxfailedaccessattempts and DefaultLockoutTimeSpan를 사용 하 여 설정할 수 있습니다.The maximum failed access attempts and lockout time can be set with MaxFailedAccessAttempts and DefaultLockoutTimeSpan. 다음은 실패 한 액세스 시도 10 분 후 10 분 동안 계정 잠금을 구성 합니다.The following configures account lockout for 10 minutes after 10 failed access attempts:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc();

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

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

PasswordSignInAsynclockoutOnFailure 다음을으로 설정 하는지 확인 합니다 true .Confirm that PasswordSignInAsync sets lockoutOnFailure to true:

var result = await _signInManager.PasswordSignInAsync(
                 Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);