Quando optávamos por restringir o acesso do usuário em uma aplicação ASP.NET, tínhamos que recorrer ao Forms Authentication. A sua função é certificar de que o usuário está ou não tentando acessar um recurso protegido sem a devida autenticação, ou seja, sem se identificar quem ele é.
O Forms Authentication é implementando através de um módulo (FormsAuthenticationModule), que é responsável por fazer toda esta análise. Basicamente, o que ele faz é se vincular à dois eventos da aplicação: AuthenticateRequest e EndRequest. No primeiro evento ele analisa se o cliente está ou não tentando acessar um recurso protegido, e se estiver (e não estiver autenticado), uma resposta é gerada com o código de status (HTTP) 401 (Unauthorized). Ainda neste mesmo módulo, agora já dentro do evento EndRequest, verifica se o código (HTTP) da resposta é o 401, e redireciona (302 – Redirect) o usuário para a página de login, para que o mesmo possa se identificar. Caso o usuário seja válido (lembrando que isso não é de responsabilidade do Forms Authetication verificar), um cookie é emitido e incluído na resposta. Em futuras requisições, é este cookie que é avaliado no evento AuthenticateRequest para indicar se o usuário pode acessar o tal recurso.
A partir das versões mais recentes do ASP.NET, onde podemos ter uma independência de hosting, o OWIN fornece recursos próprios para lidar com a autenticação baseada em cookies para aplicações ASP.NET. Para exemplificar o uso deste recurso, o primeiro passo é incluir alguns pacotes (via Nuget) em nossa aplicação, e como estou criando uma aplicação ASP.NET vazia, tive que adicionar todos os recursos que quero utilizar:
-
Microsoft.AspNet.Mvc
-
Microsoft.AspNet.WebPages
-
Microsoft.Web.Infrastructure
-
Owin
-
Microsoft.Owin
-
Microsoft.Owin.Host.SystemWeb
-
Microsoft.Owin.Security
-
Microsoft.Owin.Security.Cookies
Apesar de ASP.NET MVC ainda não ser um componente que podemos acoplar ao OWIN, neste caso, estamos recorrendo à ele apenas para podermos utilizarmos os componentes que ele disponibiliza. Neste caso especificamente, estamos falando o pacote Microsoft.Owin.Security.Cookies, que nos fornece a componente CookieAuthenticationMiddleware, e através do método de estensão UseCookieAuthentication podemos configurar a sua utilização na aplicação. Veja o exemplo a seguir:
[assembly: OwinStartup(typeof(Teste.Startup))]
namespace Teste
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = “AppTeste”,
LoginPath = new PathString(“/Seguranca/Login”)
});
}
}
}
Entre as opções, estamos configurando a propriedade AuthenticationType, que nada mais é que uma string que representa o tipo de autenticação (a mesma que é utilizada pela interface IIdentity). Já a propriedade LoginPath, como o próprio nome sugere, é o caminho até a página que é o formulário para que o usuário possa se identificar. Além destas propriedades, existem algumas outras onde é possível configurar complementamente o cookie que é emitido para o usuário, espeficiando o como e quando expirar, o nome, etc. Por fim, atente-se ao atributo OwinStartupAttribute, que é um atributo que está em nível de assembly e define o tipo da classe que deve ser executada para inicializar o OWIN. O runtime do ASP.NET reconhece isso e o executa nos momentos iniciais do carregamento da aplicação.
Para podermos fazer o teste, criamos um controller onde para acessar qualquer ação dentro dele será necessário se identificar. Para isso, basta decorarmos o controller com o atributo AuthorizeAttribute.
[Authorize]
public class TesteController : Controller
{
public ActionResult Index()
{
return View();
}
}
A partir de agora, quando tentarmos acessar o controller/ação no navegador, seremos redirecionados para a página de login configurada acima. Ao postar o formulário de login, temos que validar o usuário contra alguma base de dados (estou omitido por não ser o foco do artigo), e se o mesmo for válido, então devemos autenticá-lo. Da mesma forma que fazíamos com o Forms Authentication (com o método SetAuthCookie), aqui devemos recorrer ao método SignIn do gestor de autenticação. Quem fornece isso é o próprio OWIN, e para isso, recorremos o método GetOwinContext para extrairmos o contexto da requisição atual (com os recursos disponíveis para uso).
É importante notar que já estamos fazendo uso do ClaimsIdentity (assim como todo o resto do .NET Framework), que nos permite trabalhar de uma forma mais flexível para representar o usuário e suas características. Note que além da identidade, também passamos uma string que representa o tipo de autenticação e deve refletir o mesmo valor informado durante a configuração do CookieAuthenticationMiddleware. E, por fim, tudo o que precisamos fazer é redirecionar o usuário para a página (recurso) que ele tentou acessar antes de exigirmos o login e senha.
[HttpPost]
public ActionResult Login(System.Web.Mvc.FormCollection fc)
{
//Validar usuário em algum repositório
Request.GetOwinContext().Authentication.SignIn(
new ClaimsIdentity(
new[]
{
new Claim(ClaimTypes.Name, “Israel”),
new Claim(ClaimTypes.Email, “ia@israelaece”),
new Claim(ClaimTypes.Role, “Admin”)
}, “AppTeste”));
return Redirect(GetRedirectUrl(Request.QueryString[“ReturnUrl”]));
}
private string GetRedirectUrl(string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl) || !Url.IsLocalUrl(returnUrl))
return Url.Action(“Index”, “Teste”);
return returnUrl;
}
Para acessar os dados do usuário que está logado, podemos recorrer as seguintes propriedades: HttpContext.User, Page.User (se WebForms) e Thread.CurrentPrincipal que todas retornarão a mesma informação.