Trabalhar com identidade e autenticação dentro do ASP.NET Core é um sistema de associação que permite que você adicionar a funcionalidade de logon ao seu aplicativo. Recentemente eu escrevi uma pequena aplicação já utilizando o Razor pages
Você pode configurar a identidade do ASP.NET Core para usar um banco de dados para armazenar os nomes de usuário, senhas e dados de perfil. Como alternativa, você pode usar seu próprio armazenamento persistente, no exemplo abaixo eu foquei principalmente na autenticação como um todo, e não fiz persistência a dados para deixarmos o artigo bem focado em autenticação.
Primeiramente, vamos criar um projeto do Asp.NET Core 2.0 com Razor Pages:
Após a criação do projeto, a estrutura de pastas da solução será a seguinte:
Note que eu criei duas pastas, Model e Service, onde eu criei as respectivas classes:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace AuthCookie.Model { public class User { public string Name { get; set; } public string Email { get; set; } public string Token { get; set; } public string Password { get; set; } public string PasswordHash { get; set; } public DateTime CreateDate { get; set; } } }
using AuthCookie.Model; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace AuthCookie.Service { public interface IUserService { User Authenticate(string email, string password); } public class UserService : IUserService { public User Authenticate(string email, string password) { if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password)) return null; User user = new User { Email = email, Token = "Token", Name = "Usuário Codigo Simples" }; return user; } } }
Com isto, dentro da minha página Index, eu criei um formulário simples, onde eu irei chamar o método de autenticação;
@page @model IndexModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ ViewData["Title"] = "Home page"; } <br /> <p> @Model.Message </p> <p> Faça login: </p> <div asp-validation-summary="All"></div> <form method="POST" class="form-group"> <div>Email: <input asp-for="Customer.Email" type="email" class="input-group" /></div> <br /> <div>Password: <input asp-for="Customer.Password" type="password" class="input-group" /></div> <br /> <input type="submit" class="btn btn-default" /> </form>
E agora o codebehind da minha página Index:
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Text; using System.Threading.Tasks; using AuthCookie.Service; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; namespace AuthCookie.Pages { public class IndexModel : PageModel { //instanciando uma classe de serviço por injeção private IUserService _userService; public string Message { get; private set; } = string.Empty; public IndexModel( IUserService userService ) { _userService = userService; } //fazendo bind da model para ser usada no front-end [BindProperty] public Model.User Customer { get; set; } //metodo Get inicial public void OnGet() { //verifica se o usuário está autenticado if (User.Identity.IsAuthenticated) { Message += "Olá Usuário, você está autenticado"; } else { Message += "Você não está autenticado"; } } //metodo post do formulario public IActionResult OnPost() { if (!ModelState.IsValid) { return RedirectToPage("/Index"); } //faz a busca do usuário e verifica se existe var user = _userService.Authenticate(Customer.Email, Customer.Password); if (user == null) return Unauthorized(); //declara claim de identidade var claim = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, user.Token.ToString()) }); var claims = new[] { new Claim(ClaimTypes.Email, user.Email.ToString()) }.ToAsyncEnumerable().ToEnumerable(); //faz autenticação via Cookie var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity)); // redireciona para a Index novamente, porém já autenticado return RedirectToPage("/Index"); } } }
Com isto vimos que foi necessário apenas dois métodos, o método Get que exibe uma mensagem na página informando se o usuário está logado ou não no sistema; e um método Post que captura as informações do formulário e realiza a autenticação do usuário de fato.
Além disto, precisamos configurar como o sistema irá se comportar com a autenticação, dentro da classe Startup.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AuthCookie.Service; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; namespace AuthCookie { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddCors(); //adiciona a classe de serviço ao escopo para utilizarmos na página services.AddScoped<IUserService, UserService>(); // configura autenticação por cookie services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie(o => { o.LoginPath = new PathString("/index"); o.Cookie.Name = "codigosimples"; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseBrowserLink(); app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); } app.UseCors(x => x .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials()); //adiciona autenticação ao projeto app.UseAuthentication(); app.UseStaticFiles(); app.UseMvc(); } } }
E pronto! O sistema de autenticação deve funcionar agora sem maiores problemas. Lembrando que é um sistema simples e básico sem nenhuma validação ainda ou busca de usuário no banco, mas deve lhe ajudar e muito para criar um sistema básico de autenticação.
Todo o código está no meu github: https://github.com/jhomarolo/auth-aspnetcore
Espero que tenham gostado! Um grande abraço a todos!