Udostępnij za pośrednictwem


Uwierzytelnianie dwuskładnikowe z wiadomością SMS w programie ASP.NET Core

Przez Rick Anderson i Swiss-Devs

Ostrzeżenie

Aplikacje do uwierzytelniania dwuskładnikowego (2FA), wykorzystujące algorytm jednorazowych haseł oparty na czasie (TOTP), są zalecanym w branży podejściem do 2FA. Uwierzytelnianie 2FA przy użyciu protokołu TOTP jest preferowane do uwierzytelniania SMS 2FA. Aby uzyskać więcej informacji, zobacz Włączanie generowania kodu QR dla aplikacji uwierzytelniania TOTP w ASP.NET Core dla ASP.NET Core 2.0 i nowszych wersji.

W tym samouczku pokazano, jak skonfigurować uwierzytelnianie dwuskładnikowe (2FA) za pomocą SMS. Instrukcje są podane dla twilio i ASPSMS (https://www.aspsms.com/asp.net/identity/core/testcredits/), ale można użyć dowolnego innego dostawcy programu SMS. Zalecamy ukończenie potwierdzenia konta i odzyskiwania hasła przed rozpoczęciem tego samouczka.

Wyświetl lub pobierz przykładowy kod. Jak pobrać.

Tworzenie nowego projektu ASP.NET Core

Utwórz nową aplikację internetową platformy ASP.NET Core o nazwie Web2FA przy użyciu poszczególnych kont użytkowników. Postępuj zgodnie z instrukcjami z sekcji Wymuszanie użycia HTTPS w ASP.NET Core, aby skonfigurować i wymusić protokół HTTPS.

Tworzenie konta SMS

Utwórz konto SMS, na przykład w usługach twilio lub ASPSMS (https://www.aspsms.com/asp.net/identity/core/testcredits/). Rejestruj poświadczenia uwierzytelniania (dla usługi twilio: accountSid i authToken, dla usługi ASPSMS: Userkey i Password).

Określanie poświadczeń dostawcy programu SMS

Twilio:

Na karcie Pulpit nawigacyjny Twojego konta Twilio skopiuj identyfikator SID konta oraz token uwierzytelniania.

ASPSMS:

W ustawieniach konta przejdź do Userkey i skopiuj go razem z Password.

Później zapiszemy te wartości za pomocą narzędzia secret-manager w ramach kluczy SMSAccountIdentification i SMSAccountPassword.

Określanie identyfikatora nadawcy/inicjatora

Twilio: Na karcie Numery skopiuj numer telefonu usługi Twilio.

ASPSMS: W menu Odblokowywania Nadawców, odblokuj jednego lub więcej Nadawców lub wybierz alfanumeryczny Nadawcę (nie są obsługiwane przez wszystkie sieci).

Później zapiszemy tę wartość za pomocą narzędzia menedżera tajemnic w kluczu SMSAccountFrom.

Podaj poświadczenia dla usługi SMS

Użyjemy wzorce opcji w celu uzyskania dostępu do konta użytkownika oraz kluczowych ustawień.

  • Utwórz klasę, aby pobrać bezpieczny klucz SMS. W tym przykładzie klasa SMSoptions jest tworzona w pliku Services/SMSoptions.cs.
namespace Web2FA.Services
{
    public class SMSoptions
    {
        public string SMSAccountIdentification { get; set; }
        public string SMSAccountPassword { get; set; }
        public string SMSAccountFrom { get; set; }
    }
}

Ustaw SMSAccountIdentification, SMSAccountPassword i SMSAccountFrom za pomocą narzędzia secret-manager. Na przykład:

C:/Web2FA/src/WebApp1>dotnet user-secrets set SMSAccountIdentification 12345
info: Successfully saved SMSAccountIdentification = 12345 to the secret store.
  • Dodaj pakiet NuGet dla dostawcy programu SMS. Z poziomu konsoli menedżera pakietów (PMC) uruchom polecenie:

Twilio:

Install-Package Twilio

ASPSMS:

Install-Package ASPSMS

  • Dodaj kod w pliku Services/MessageServices.cs, aby włączyć program SMS. Użyj sekcji Twilio lub ASPSMS:

Twilio:

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);
        }
    }
}

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);
        }
    }
}

Skonfiguruj uruchamianie, aby używać SMSoptions

Dodaj SMSoptions do kontenera usługi w metodzie ConfigureServices w Startup.cs:

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

Włączanie uwierzytelniania dwuskładnikowego

Otwórz plik widoku Views/Manage/Index.cshtmlRazor i usuń znaki komentarza (więc żaden znacznik nie jest komentowany).

Logowanie przy użyciu uwierzytelniania dwuskładnikowego

  • Uruchamianie aplikacji i rejestrowanie nowego użytkownika

Widok rejestracji aplikacji internetowej otwarty w programie Microsoft Edge

  • Naciśnij nazwę użytkownika, która aktywuje metodę akcji Index w obszarze Zarządzanie kontrolerem. Następnie naciśnij numer telefonu Dodaj link.

Zarządzaj widokiem — naciśnij link

  • Dodaj numer telefonu, który otrzyma kod weryfikacyjny, a następnie naciśnij pozycję Wyślij kod weryfikacyjny.

strona dodawania numeru telefonu

  • Otrzymasz wiadomość SMS z kodem weryfikacyjnym. Wprowadź go i naciśnij Prześlij

strona weryfikacji numeru telefonu

Jeśli nie otrzymasz wiadomości SMS, zobacz stronę dziennika usługi twilio.

  • Widok Zarządzaj pokazuje, że numer telefonu został dodany pomyślnie.

widok zarządzania — pomyślnie dodano numer telefonu

  • Stuknij Włącz, aby włączyć uwierzytelnianie dwuskładnikowe.

Zarządzanie widokiem — włączanie uwierzytelniania dwuskładnikowego

Testowanie uwierzytelniania dwuskładnikowego

  • Wyloguj się.

  • Zaloguj się.

  • Konto użytkownika włączyło uwierzytelnianie dwuskładnikowe, więc musisz podać drugi czynnik uwierzytelniania. W tym samouczku włączono weryfikację telefonu. Wbudowane szablony umożliwiają również skonfigurowanie poczty e-mail jako drugiego czynnika. Możesz skonfigurować dodatkowe czynniki weryfikacji dwuetapowej na potrzeby uwierzytelniania, takie jak kody QR. Naciśnij Prześlij.

wysyłanie widoku kodu weryfikacyjnego

  • Wprowadź kod otrzymany w wiadomości SMS.

  • Kliknięcie na pole wyboru Zapamiętaj tę przeglądarkę sprawi, że nie będzie konieczności używania uwierzytelniania 2FA podczas logowania się, jeśli korzystasz z tego samego urządzenia i przeglądarki. Włączenie uwierzytelniania 2FA i kliknięcie na Zapamiętaj tę przeglądarkę zapewni użytkownikowi silną ochronę 2FA przed złośliwymi użytkownikami próbującymi uzyskać dostęp do jego konta, pod warunkiem, że nie mają dostępu do jego urządzenia. Można to zrobić na dowolnym urządzeniu prywatnym, którego regularnie używasz. Ustawiając Zapamiętaj tę przeglądarkę, uzyskujesz dodatkowe zabezpieczenia dzięki 2FA na urządzeniach, których nie używasz regularnie, i masz wygodę, że nie musisz przechodzić przez uwierzytelnianie 2FA na własnych urządzeniach.

Zweryfikuj widok

Blokada konta w celu ochrony przed atakami siłowymi

Blokada konta jest zalecana w przypadku uwierzytelniania 2FA. Gdy użytkownik zaloguje się za pośrednictwem konta lokalnego lub konta społecznościowego, każda nieudana próba 2FA jest przechowywana. Jeśli zostanie osiągnięta maksymalna liczba nieudanych prób dostępu, użytkownik zostanie zablokowany (domyślnie: 5 minut blokady po 5 nieudanych próbach dostępu). Pomyślne uwierzytelnienie resetuje liczbę nieudanych prób dostępu i resetuje zegar. Maksymalna liczba nieudanych prób dostępu i czas blokady można ustawić przy użyciu MaxFailedAccessAttempts i DefaultLockoutTimeSpan. Poniżej skonfigurowano blokadę konta przez 10 minut po 10 nieudanych próbach dostępu:

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);
}

Upewnij się, że PasswordSignInAsync ustawia lockoutOnFailure na true:

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