Compartilhar via


Aplicativo ASP.NET MVC 5 com autenticação por SMS e email Two-Factor

Rick Anderson

Este tutorial mostra como criar um aplicativo Web ASP.NET MVC 5 com autenticação de dois fatores. Você deve concluir Criar um aplicativo Web ASP.NET MVC 5 seguro com logon, confirmação de email e redefinição de senha antes de continuar. Você pode baixar o aplicativo concluído aqui. O download contém auxiliares de depuração que permitem testar a confirmação de email e o SMS sem configurar um provedor de email ou SMS.

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

Criar um aplicativo ASP.NET MVC

Comece instalando e executando Visual Studio Express 2013 para Web ou uma versão mais recente.

Observação

Aviso: você deve concluir Criar um aplicativo Web ASP.NET MVC 5 seguro com logon, confirmação de email e redefinição de senha antes de continuar. Você deve instalar Visual Studio 2013 atualização 3 ou superior para concluir este tutorial.

  1. Crie um novo projeto Web ASP.NET e selecione o modelo MVC. O Web Forms também dá suporte ao ASP.NET Identity, assim você poderá seguir etapas semelhantes em um aplicativo Web Forms.
    Captura de tela mostrando a janela Novo projeto ASP.NET. Em destaque a autenticação padrão, Contas de Usuário Individuais.
  2. Deixe a autenticação padrão como Contas de Usuário Individuais. Se você quiser hospedar o aplicativo no Azure, deixe a caixa de seleção marcada. Mais adiante no tutorial, faremos a implantação no Azure. Você pode abrir gratuitamente uma conta do Azure.
  3. Defina o projeto para usar SSL.

Configurar o SMS para autenticação de dois fatores

Este tutorial contém instruções sobre como usar o Twilio ou o ASPSMS, mas você pode usar qualquer outro provedor de SMS.

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

    Crie uma conta de Twilio ou uma conta de ASPSMS.

  2. Instalando pacotes adicionais ou adicionando 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 mostrando a janela Adicionar referência de serviço. As barras de entrada Endereço e Namespace estão realçadas.

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

    Namespace:
    ASPSMSX2

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

É recomendável usar a 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 segredos e chaves de criptografia, como certificados, cadeias de conexão e senhas. Para .NET Aspire, consulte Comunicação segura entre hospedagem e integrações de cliente.

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

  • Expõe a senha do usuário para o cliente.
  • Esse é um risco de segurança importante.
  • Use apenas quando outros fluxos de autenticação não forem 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 com um servidor de banco de dados de teste. Geralmente, as variáveis de ambiente são armazenadas em texto sem formatação e não criptografado. Se o computador ou o processo estiver comprometido, as variáveis de ambiente poderão ser acessadas por partes não confiáveis. Não recomendamos o uso de variáveis de ambiente para armazenar uma cadeia de conexão de produção, pois essa 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 nos arquivos de configuração de texto sem formatação.
  • Não use segredos de produção em ambientes de teste ou de desenvolvimento.
  • Especifique segredos fora do projeto para que eles não sejam acidentalmente comprometidos com um repositório de código-fonte.

Twilio:
Na guia Painel da sua conta do Twilio, copie a SID da Conta e Auth token.

ASPSMS:
Nas configurações da sua conta, navegue até Userkey e copie-o junto com a sua Senha autodefinida .

Posteriormente, armazenaremos esses valores no arquivo web.config nas chaves "SMSAccountIdentification" e "SMSAccountPassword". 4. Especificando SenderID/Originator

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

ASPSMS:
No menu Unlock Originators, desbloqueie um ou mais originadores ou escolha um originador alfanumérico (nem todas as redes oferecem suporte).

Posteriormente, armazenaremos esse valor no arquivo web.config na chave "SMSAccountFrom". 5. Transferir credenciais do 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. Ao implantar no Azure, podemos armazenar os valores com segurança na seção configurações do aplicativo na guia Configurar 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 da 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 basta remover 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 logon usando a conta que você registrou anteriormente.

  5. Clique em sua ID de Usuário, que ativa o Index método de ação no controlador de Manage.
    Captura de tela mostrando a página inicial do aplicativo ASP.NET. Um exemplo de ID de usuário está em destaque.

  6. Clique em Adicionar.
    Captura de tela mostrando a página Configurações da conta do aplicativo A S P dot NET. Nenhum Adicionar ao lado da seção Número de telefone é destacado.

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

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

    Captura de tela mostrando a página para adicionar número de telefone do aplicativo ASP.NET. Um número de telefone de exemplo é preenchido com um botão para enviar código de verificação abaixo dele.

  8. Em alguns segundos, você receberá uma mensagem de texto contendo o código de verificação. Insira e pressione Enviar.
    Captura de tela da página para adicionar número de telefone do aplicativo ASP.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 exibição Gerenciar mostra que o número de telefone foi adicionado.

Habilitar a 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 habilitar a 2FA, clique em sua ID de usuário (alias de email) na barra de navegação.

Captura de tela exibindo a página inicial do aplicativo ASP.NET. Um exemplo de ID de usuário está em destaque.

Clique em habilitar 2FA..

Captura de tela que mostra a página Configurações da Conta do aplicativo ASP.NET. Two-Factor Autenticação: Desabilitada com uma seção onde o link para Habilitar está destacado.

Saia e entre novamente. Se você habilitou o email (consulte o tutorial anterior), selecione o SMS ou o email para 2FA.

Captura de tela mostrando a página Enviar código de verificação do aplicativo ASP.NET. Um menu suspenso mostrando o Código de telefone e Código de email é selecionado.

É exibida a página de verificação do código, onde você pode digitar o código (recebido por SMS ou email).

Captura de tela mostrando a página Verificar do aplicativo ASP.NET para 2 FA. Abaixo de um código de exemplo, uma caixa de seleção com Lembrar este navegador é destacada.

Clicar na caixa de seleção Lembrar deste navegador isentará você de usar a autenticação bifatorial para fazer login ao usar o navegador e o dispositivo nos quais marcou a caixa. Desde que usuários mal-intencionados não consigam acessar seu dispositivo, habilitar a bifatorial e clicar no Lembrar este navegador dará a você acesso prático por senha em uma única etapa, mantendo ao mesmo tempo uma forte proteção de autenticação bifatorial todo acesso de dispositivos não confiáveis. Você pode fazer isso em qualquer dispositivo privado que utilize regularmente.

Este tutorial apresenta uma rápida introdução sobre como habilitar a 2FA em um novo aplicativo ASP.NET MVC. Meu tutorial autenticação em duas etapas usando SMS e email com ASP.NET Identity explora em detalhes o código que está por trás do exemplo.

Recursos adicionais