Alura > Cursos de Programação > Cursos de .NET > Conteúdos de .NET > Primeiras aulas do curso Segurança com ASP.NET Core: proteja aplicações Web

Segurança com ASP.NET Core: proteja aplicações Web

ASP.NET Core Identity - Apresentaçãoão

Olá! Meu nome é Marcelo Oliveira, integrante da Escola de Programação, e serei seu instrutor nesta jornada!

Audiodescrição: Marcelo se descreve como um homem branco, de cabelos e barba preto com alguns fios grisalhos. Usa óculos de grau com armação preta e veste uma camiseta cinza. Ao fundo, uma parede iluminada em tom azul.

Você já teve sua sessão expirada em algum site? Sabe por que isso acontece? Neste curso, vamos explorar a fundo o conceito de sessões e aprender a implementar autenticação em sites utilizando AspNet Core.

Trabalharemos com o projeto AspNet Core da Clínica Vollmed, responsável pelo gerenciamento de dados de médicos e consultas. Inicialmente, a aplicação não conta com uma camada de segurança, mas ao longo das aulas, vamos implementá-la passo a passo.

Começaremos instalando o AspNet Core Identity, configurando o Visual Studio e criando usuários de teste. Com os usuários cadastrados, faremos login e navegaremos pela aplicação. Em seguida, entenderemos o que é um ataque CSRF e aprenderemos a proteger a aplicação contra essa vulnerabilidade. Também implementaremos uma regra para garantir que as pessoas usuárias só possam acessar a aplicação após confirmarem seus e-mails, como indicado na mensagem "Thank you for confirming your email."

Outro aspecto essencial da segurança é limitar as tentativas de login e configurar requisitos para senhas fortes. Depois, estudaremos o funcionamento das sessões e seu armazenamento em cookies, além de aprender como proteger nossa aplicação contra o sequestro de sessões, conhecido como hijacking.

Na sequência, abordaremos a validação de dados de entrada, exibindo mensagens de erro apropriadas, e exploraremos estratégias para evitar ataques de injeção de JavaScript (XSS). Finalizaremos o curso protegendo controllers e views, além de adicionar informações personalizadas aos usuários por meio de claims.

O conhecimento adquirido neste curso de segurança com AspNet Core certamente fará a diferença em seus projetos. Aproveite os recursos da plataforma Alura, que vão além dos vídeos e incluem atividades, o apoio da comunidade em nosso fórum e no Discord.

Vamos nessa!

ASP.NET Core Identity - Instalando ASP.NET Core Identity

Olá! Vamos dar início a aula 1, onde implementaremos o AspNet Core Identity.

Trabalharemos com o projeto AspNet Core da clínica Vollmed, que foi baixado na etapa de preparação do ambiente. Atualmente, essa aplicação não possui um mecanismo de autenticação. Para solucionar isso, instalaremos o AspNet Core Identity.

Instalando o Pacote Necessário

Antes de prosseguir com a instalação, precisamos adicionar um pacote essencial ao projeto: Microsoft.AspNetCore.Identity.EntityFrameworkCore.

A instalação será feita no projeto MedVoll.Web. Para isso, clicamos com o botão direito do mouse do mouse sobre o projeto, selecionamos "Manage NuGet Packages" e, na barra de busca, colamos o nome do pacote Microsoft.AspNetCore.Identity.EntityFrameworkCore. Escolhemos a versão 9.0.0 e clicamos para instalar.

Modificando a Classe ApplicationDbContext

Com o pacote instalado, o próximo passo é modificar a classe de contexto da aplicação, localizada na pasta Data. Nessa pasta, encontramos o arquivo ApplicationDbContext.cs, que declara a classe ApplicationDbContext na linha 6.

 public class ApplicationDbContext : DbContext
    {

Atualmente, essa classe herda de DbContext, mas queremos que ela herde de IdentityDbContext.

public class ApplicationDbContext : IdentityDbContext
    {

Essa mudança permitirá a inclusão automática de estruturas para gerenciar usuários e papéis, fundamentais para autenticação e autorização.

Ao fazer essa alteração na linha 6, pode ser que o Visual Studio não reconheça a classe IdentityDbContext, pois o namespace necessário ainda não foi adicionado. Para corrigir isso rapidamente, basta utilizar o atalho "Ctrl + ." e selecionar a opção "Using Microsoft.AspNetCore.Identity.EntityFrameworkCore".

Adicionando a Estrutura de Identidade

Agora, vamos adicionar a estrutura necessária para segurança, autenticação e autorização do projeto.

Para isso, clicamos com o botão direito do mouse sobre o nome do projeto, selecionamos "Add" e, no painel central, escolhemos "New Scaffolded Item". Na janela que se abre, selecionamos "Identity" tanto no menu lateral quanto no painel central e clicamos em "Add".

Em seguida, definimos quais views serão incluídas no projeto, como as telas de cadastro e login. Selecionamos "Account/Login" e "Account/Register". Na parte inferior da janela, escolhemos a classe de contexto ApplicationDbContext e clicamos novamente em "Add".

Com isso, a estrutura necessária foi gerada. Dentro do projeto, na pasta Areas, encontramos a subpasta Identity e, dentro dela, Pages. Em Pages, localizamos a pasta Account, que contém os arquivos Login.cshtml e Register.cshtml, responsáveis pelas telas de login e cadastro respectivamente.

Criando a Migração para o Banco de Dados

Agora, precisamos refletir essa nova estrutura no banco de dados, criando tabelas para usuários, papéis e outras informações relacionadas. Para isso, vamos gerar uma Migration (migração).

No Visual Studio, abrimos o terminal acessando View> Terminal" e navegamos até a pasta do projeto MedVoll.Web com o comando:

cd MedVoll.Web

Em seguida, executamos o seguinte comando para criar a migração:

dotnet ef migrations add CreateIdentitySchema

Neste comando, CreateIdentitySchema corresponde ao nome da migração.

Após pressionar "Enter", a migração será gerada e poderá ser encontrada na pasta Data, dentro da subpasta Migrations, no arquivo CreateIdentitySchema.cs. Esse arquivo contém todas as instruções necessárias para adicionar novas tabelas ao nosso banco de dados.

Aplicando a Migração ao Banco de Dados

Para aplicar a migração, abrimos novamente o terminal, navegamos até a pasta MedVoll.Web com cd MedVoll.Web e executamos o seguinte comando:

dotnet ef database update

Esse comando atualizará o banco de dados com as alterações pendentes da migração.

Após a aplicação, podemos localizar o banco de dados atualizado no painel à direita, no arquivo vollmed.db. Para visualizá-lo, clicamos com o botão direito do mouse sobre o arquivo, selecionamos "Abrir com" e escolhemos o aplicativo DB Browser for SQLite, que foi instalado durante a preparação do ambiente.

Ao abrir o banco de dados, podemos visualizar as tabelas criadas pela migração, incluindo AspNetUsers e AspNetRoles, responsáveis pelo gerenciamento de usuários e papéis.

Conclusão e Próximos Passos

O AspNet Core Identity é uma solução integrada para gerenciar autenticação, registro de pessoas usuárias e permissões, oferecendo suporte à extensibilidade. Ao instalá-lo, adicionamos ao projeto uma estrutura que servirá de base para o curso. Com apenas alguns passos, configuramos as tabelas de pessoas usuárias e papéis e implementamos as telas de login e cadastro.

No próximo vídeo, aprenderemos a criar um usuário de teste para validar a funcionalidade do AspNet Core Identity.

ASP.NET Core Identity - Adicionando usuários de teste

Agora que nossa aplicação conta com o ASP NET Core Identity integrado, enfrentamos um desafio: ainda não temos usuários de teste para facilitar as operações. Para validar o acesso, as permissões e as ações de indicação, precisamos criar esses usuários.

Neste vídeo, adicionaremos usuários de teste. No Visual Studio, aprenderemos a desenvolver o código necessário para essa criação. Esse código incluirá uma nova classe com métodos responsáveis por verificar se o usuário ou o papel já existem, inserindo-os apenas quando necessário. Como essa implementação pode ser trabalhosa, utilizaremos um código previamente feito para tornar o processo mais ágil.

Criando a Classe IdentitySeeder

O primeiro passo é criar uma nova classe para popular as tabelas de usuários e papéis. No projeto MedVoll.Web, localizamos a pasta Data. Clicamos com o botão direito do mouse sobre ela, selecionamos "Add" e escolhemos "Class". Nomearemos a classe como IdentitySeeder. O termo "Seeder" significa "semeador", pois estamos preenchendo as tabelas de identidade da aplicação. Após clicar em "Add", a classe será criada com um código padrão. Substituiremos esse código pelo código a seguir:

using Microsoft.AspNetCore.Identity;

namespace MedVoll.Web.Data
{
    public class IdentitySeeder
    {
        public static async Task SeedUsersAsync(IServiceProvider serviceProvider)
        {
            var userManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();
            var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
            // Verifica e cria a função "User", se necessário
            const string userRole = "User";
            if (!await roleManager.RoleExistsAsync(userRole))
            {
                await roleManager.CreateAsync(new IdentityRole(userRole));
            }
            // Cria os usuários
            await CreateUserAsync(userManager, "alice@smith.com", "Password@123", userRole);
            await CreateUserAsync(userManager, "bob@smith.com", "Password@123", userRole);
        }
        private static async Task CreateUserAsync(UserManager<IdentityUser> userManager, string email, string password, string role)
        {
            // Verifica se o usuário já existe
            if (await userManager.FindByEmailAsync(email) != null)
            {
                return;
            }
            var user = new IdentityUser
            {
                UserName = email,
                Email = email,
                EmailConfirmed = true // Para evitar a necessidade de confirmação de email
            };
            // Cria o usuário
            var result = await userManager.CreateAsync(user, password);
            if (result.Succeeded)
            {
                // Atribui a função ao usuário
                await userManager.AddToRoleAsync(user, role);
            }
            else
            {
                throw new Exception($"Erro ao criar usuário {email}: {string.Join(", ", result.Errors)}");
            }
        }
    }
}

Na classe IdentitySeeder, há dois métodos principais: SeedUsersAsync e CreateUsersAsync. O primeiro instancia as classes userManager e roleManager, responsáveis pelo gerenciamento de usuários e papéis. Ele verifica se o papel User já existe e, caso contrário, o cria. Em seguida, chama o método CreateUsersAsync para registrar dois usuários com os e-mails alice@smith.com e bob@smith.com.

O método privado CreateUsersAsync verifica se o usuário já está cadastrado. Se estiver, nenhuma ação é realizada; caso contrário, o usuário é criado no banco de dados e associado ao papel User.

Modificando a Classe Program

Para que a classe Program possa chamar o método público da IdentitySeeder, é necessário modificar a classe Program. No arquivo Program.cs, localizamos a chamada do método AddDefaultIdentity. Antes de .AddEntityFrameworkStores, que está por volta da linha 23, adicionaremos uma chamada para o método .AddRoles, especificando IdentityRole como tipo.

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

Essa inclusão garante que o IdentitySeeder possa ser chamado corretamente e adicionar usuários aos papéis.

Chamando o IdentitySeeder na Inicialização

O passo final é fazer com que a classe Program chame o método SeedUsersAsync da IdentitySeeder. Para isso, no final da classe Program, antes de app.Run(), criaremos um escopo a partir do objeto Services e chamaremos SeedUsersAsync, passando o ServiceProvider para permitir a injeção de dependências entre as classes.

Este é o código de implementação:

using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    try
    {
        await IdentitySeeder.SeedUsersAsync(services);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Erro ao executar o Seeder: {ex.Message}");
    }
}

Testando a Implementação

Agora podemos executar a aplicação pressionando "F5". O website será aberto normalmente, como nos passos anteriores do curso. Durante a execução, a aplicação popula o banco de dados com os usuários e papéis definidos.

Para verificar os dados inseridos, voltamos ao projeto e abrimos o arquivo de banco de dados vollmed.db, que contém as tabelas utilizadas pela aplicação. Na aba "Browse Data", selecionamos a tabela AspNetUsers para visualizar os registros dos usuários alice@smith.com e bob@smith.com. Na tabela AspNetRoles, há um registro correspondente ao papel User. Já a tabela AspNetUserRoles estabelece a associação entre os usuários e seus respectivos papéis.

Conclusão e Próximos Passos

O seeding de dados é uma técnica utilizada para inicializar um banco de dados com dados padrão de teste, muito útil em ambientes de desenvolvimento e testes, onde a agilidade é essencial.

Neste vídeo, implementamos a classe IdentitySeeder, que utiliza as classes RoleManager e UserManager do ASP NET Core Identity para gerenciar papéis e usuários. Com os usuários criados, estamos prontos para configurar a autorização básica no próximo vídeo.

Sobre o curso Segurança com ASP.NET Core: proteja aplicações Web

O curso Segurança com ASP.NET Core: proteja aplicações Web possui 146 minutos de vídeos, em um total de 56 atividades. Gostou? Conheça nossos outros cursos de .NET em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda .NET acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas