Partilhar via


ASP.NET aplicação MVC 5 com autenticação de Two-Factor por SMS e e-mail

por Rick Anderson

Este tutorial mostra como criar um aplicativo Web MVC 5 ASP.NET com Autenticação Two-Factor. Você deve concluir Criar um aplicativo Web MVC 5 ASP.NET seguro com login, confirmação de e-mail e redefinição de senha antes de prosseguir. Pode descarregar a aplicação concluída aqui. O download contém auxiliares de depuração que permitem testar a confirmação de e-mail e SMS sem configurar um provedor de e-mail ou SMS.

Este tutorial foi escrito por Rick Anderson ( Twitter: @RickAndMSFT ).

Criar um aplicativo MVC ASP.NET

Comece instalando e executando o Visual Studio Express 2013 para Web ou superior.

Observação

Aviso: Você deve concluir Criar um aplicativo Web MVC 5 ASP.NET seguro com login, confirmação de e-mail e redefinição de senha antes de prosseguir. Você deve instalar Visual Studio 2013 Update 3 ou superior para concluir este tutorial.

  1. Crie um novo projeto ASP.NET Web e selecione o modelo MVC. Os Web Forms também suportam ASP.NET Identidade, pelo que pode seguir passos semelhantes numa aplicação de formulários Web.
    Captura de tela que mostra a janela New A S P dot NET Project. A autenticação padrão, Contas de Usuário Individual, é realçada.
  2. Deixe a autenticação padrão como Contas de Utilizador Individual. Se você quiser hospedar o aplicativo no Azure, deixe a caixa de seleção marcada. Mais adiante no tutorial, implantaremos no Azure. Você pode abrir uma conta da Azure gratuitamente.
  3. Defina o projeto para usar SSL.

Configurar o SMS para autenticação de dois fatores

Este tutorial fornece instruções para usar o Twilio ou ASPSMS, mas você pode usar qualquer outro provedor de SMS.

  1. Criar uma conta de usuário com um provedor de SMS

    Crie uma conta Twilio ou uma conta ASPSMS.

  2. Instalação de pacotes adicionais ou adição de referências de serviço

    Twilio:
    No Console do Gerenciador de Pacotes, digite o seguinte comando:
    Install-Package Twilio

    ASPSMS:
    A seguinte referência de serviço precisa ser adicionada:

    Captura de tela que mostra a janela Adicionar Referência de Serviço. As barras de entrada Address e Namespace são realçadas.

    Endereço:
    https://webservice.aspsms.com/aspsmsx2.asmx?WSDL

    Espaço de nomes:
    ASPSMSX2

  3. Descobrindo as credenciais do usuário do provedor de SMS

Recomendamos o uso da opção de autenticação segura mais segura. Para aplicativos .NET implantados no Azure, consulte:

O Azure Key Vault e .NET Aspire fornecem a maneira mais segura de armazenar e recuperar segredos. O Azure Key Vault é um serviço de nuvem que protege chaves de criptografia e segredos como certificados, cadeias de conexão e senhas. Para o .NET Aspire, consulte Comunicação segura entre hospedagem e integrações de cliente.

Evite a concessão de credenciais de senha do proprietário do recurso porque:

  • Expõe a senha do usuário para o cliente.
  • É um risco de segurança significativo.
  • Só deve ser usado quando outros fluxos de autenticação não são possíveis.

Quando o aplicativo é implantado em um servidor de teste, uma variável de ambiente pode ser usada para definir a cadeia de conexão para um servidor de banco de dados de teste. As variáveis de ambiente geralmente são armazenadas em texto simples e não criptografado. Se a máquina ou o processo estiver comprometido, as variáveis de ambiente podem ser acessadas por partes não confiáveis. Recomendamos não usar variáveis de ambiente para armazenar uma cadeia de conexão de produção, pois não é a abordagem mais segura.

Diretrizes de dados de configuração:

  • Nunca armazene senhas ou outros dados confidenciais no código do provedor de configuração ou em arquivos de configuração de texto simples.
  • Não use segredos de produção em ambientes de desenvolvimento ou teste.
  • Especifique segredos fora do projeto para que eles não possam ser acidentalmente comprometidos em um repositório de código-fonte.

Twilio:
Na guia Painel da sua conta Twilio, copie o Account SID e o Token de Autenticação.

ASPSMS:
Nas definições da sua conta, navegue até Userkey e copie-a juntamente com a sua senha auto-definida.

Mais tarde, armazenaremos esses valores no arquivo web.config dentro das chaves "SMSAccountIdentification" e "SMSAccountPassword" . 4. Especificando o Identificador do Remetente / Originador

Twilio:
Na guia Números, copie seu número de telefone Twilio.

ASPSMS:
No menu Desbloquear Originadores, desbloqueie um ou mais Originadores ou escolha um Originador alfanumérico (esta opção não é suportada por todas as redes).

Mais tarde, armazenaremos esse valor no arquivo web.config dentro da chave "SMSAccountFrom" . 5. Transferir credenciais de provedor de SMS para o aplicativo

Disponibilize as credenciais e o número de telefone do remetente para o aplicativo. Para simplificar, armazenaremos esses valores no arquivo web.config. Quando implantamos no Azure, podemos armazenar os valores com segurança na seção de configurações do aplicativo na guia configurar do site.

[!code-xml[Main](aspnet-mvc-5-app-with-sms-and-email-two-factor-authentication/samples/sample1.xml?highlight=8-10)]

> [!WARNING]
> Security - Never store sensitive data in your source code. The account and credentials are added to the code above to keep the sample simple. See [Best practices for deploying passwords and other sensitive data to ASP.NET and Azure](../../../identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure.md).
  1. Implementação de transferência de dados para o provedor de SMS

    Configure a classe SmsService no arquivo App_Start\IdentityConfig.cs.

    Dependendo do provedor de SMS usado, ative a seção Twilio ou a seção 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
        }
    }
    
  2. Atualize o modo de exibição Views\Manage\Index.cshtml Razor: (Observação: não remova apenas os comentários no código de saída, use o código abaixo.)

    @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>
    
  3. Verifique se os métodos de ação EnableTwoFactorAuthentication e DisableTwoFactorAuthentication no ManageController têm o atributo [ValidateAntiForgeryToken]:

    //
    // 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");
    }
    
  4. Execute o aplicativo e faça login com a conta que você registrou anteriormente.

  5. Clique no seu ID de Utilizador que ativa o método de ação Index no controlador Manage.
    Captura de ecrã que mostra a página inicial da aplicação ASP.NET. Um exemplo de ID de usuário é realçado.

  6. Clique em Adicionar.
    Captura de ecrã que mostra a página Definições de Conta da aplicação A S P PT. Nenhuma adição ao lado da seção Número de telefone está realçada.

  7. O método de ação AddPhoneNumber exibe uma caixa de diálogo para inserir um número de telefone que pode receber mensagens SMS.

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

    Captura de tela que mostra a página Adicionar Número de Telefone do aplicativo A S P dot NET. Um número de telefone de exemplo é preenchido com um botão Enviar código de verificação abaixo dele.

  8. Em poucos segundos você receberá uma mensagem de texto com o código de verificação. Insira-o e prima o botão Enviar.
    Captura de ecrã da página Adicionar Número de Telefone da aplicação A S P NET mostrando uma barra de entrada preenchida com um código de verificação de exemplo e um botão Enviar abaixo dela.

  9. A vista Gerir mostra que o seu número de telefone foi adicionado.

Habilitar autenticação de dois fatores

No aplicativo gerado pelo modelo, você precisa usar a interface do usuário para habilitar a autenticação de dois fatores (2FA). Para ativar o 2FA, clique no seu ID de utilizador (alias de e-mail) na barra de navegação.

Captura de tela que exibe a página inicial do aplicativo A S P dot NET. Um exemplo de USER I D é realçado.

Clique em ativar 2FA.

Captura de ecrã que mostra a página Definições de Conta da aplicação A S P dot NET. Two-Factor Autenticação: Desativada com uma secção onde a ligação para ativar está realçada.

Termine sessão e, em seguida, inicie sessão novamente. Se você ativou o e-mail (veja meu tutorial anterior), você pode selecionar o SMS ou e-mail para 2FA.

Captura de tela que mostra a página Enviar código de verificação do aplicativo A S P net. Um menu suspenso mostrando Código de telefone e Código de e-mail está selecionado.

A página Verificar código é exibida onde você pode inserir o código (por SMS ou e-mail).

Captura de ecrã que mostra a página Verificar da aplicação ASP.NET para autenticação de dois fatores. Abaixo de um código de exemplo, uma caixa de seleção com Lembrar este navegador é realçada.

Clicar na caixa de seleção Lembrar este navegador isentará você da necessidade de usar 2FA para fazer login ao usar o navegador e o dispositivo onde você marcou a caixa. Desde que os utilizadores maliciosos não consigam aceder ao seu dispositivo, ativar o 2FA e clicar em Lembrar este navegador irá proporcionar acesso com senha de forma conveniente numa única etapa, enquanto mantém uma forte proteção 2FA para todos os acessos de dispositivos não confiáveis. Pode fazê-lo em qualquer dispositivo privado que utilize regularmente.

Este tutorial fornece uma introdução rápida para habilitar o 2FA em um novo aplicativo ASP.NET MVC. Meu tutorial Autenticação de dois fatores usando SMS e e-mail com ASP.NET Identity entra em detalhes sobre o código por trás do exemplo.

Recursos adicionais