Arquivo

Posts Tagged ‘ASP.NET MVC’

Configurando RoleProvider Estático em ASP.NET MVC

Olá pessoal!

Por muitas vezes nos deparamos com a necessidade implantar novas funcionalidades em nossos projetos e, em muitos casos, nunca trabalhamos com essas funcionalidades. Quando entrei no mundo MVC (veja aqui alguns pontos sobre o MVC), um dos novos desafios era criar um Membership e RoleProvider somente por código. Depois de muito bater a cabeça na época, consegui encontrar uma forma funcional e simples de realizar isso e agora compartilho com vocês. Lembrando que há muitas formas de fazer isso e essa é apenas uma delas. J

Assim, o objetivo deste artigo é demonstrar como podemos configurar um Membership com Roles já previamente definidas por nós.

Para tanto, criei um projeto em MVC 3, com a ViewEngine padrão (caso deseje saber mais sobre ViewEngines, clique aqui) e EntityFramework para persistência dos dados. Realizei algumas modificações no projeto padrão do MVC e o deixei com a estrutura demonstrada na Figura 01.

Figura 01 – Estrutura inicial do projeto

Dentro da pasta “Models”, há o arquivo do EntityFramework “DB.edmx” que foi gerado a partir de 3 tabelas: tbUsuarios, tbPermissoes e tbUsuariosPermissoes (Figura 02). Percebam que a tabela tbUsuariosPermissoes tornou-se uma Associação no edmx. A idéia é: tbUsuarios guardar dados dos usuários, tbPermissoes guardar roles previamente definidas e tbUsuariosPermissoes guardar dados de quais usuários tem quais permissões ou roles. Por convenção, não nomeei a tbPermissoes como tbRoles para que não houvesse confusão com a palavras-chave “Roles” do próprio ASP.NET.

Figura 02 – Tabelas e o edmx criado.

Configuradas as páginas e o banco, o próximo passo é criar as configurações de permissões. Clique com o direito em do projeto “Site” e adicione uma nova pasta chamada “MembershipRoleProvider”. Dentro dessa

Adicione então uma nova classe chamada “ConfigProvider” nessa nova pasta e adicione, nessa nova classe, os namespaces “System.Web.Security” e “Site.Models”. Em seguida, faça com que essa classe herde de “RoleProvider”. Perceba que ao realizamos essa herança de classes, aparecerá um pequeno traço azul em baixo da classe “RoleProvider”. Se clicarmos nesse traço, veremos que o Visual Studio nos fornecerá uma opção para implementar essa classe e então o faça (Figura 03).

Figura 03 – Herdando de RoleProvider e implementando seus métodos

Perceba que ao implementarmos o RoleProvider, alguns métodos surgirão, mas somente um deles será importante para este artigo: GetRolesForUser. Dentro deste método, iremos verificar quais as permissões que o usuário possui (Figura 04).

Figura 04 – Selecionando permissões do usuário

Antes de configurarmos uma ActionResult para que ela somente seja acessada por usuários com aquelas permissões/roles, precisamos dar uma breve explicação sobre o atributo “Authorize”. Caso você precise que uma ActionResult somente possa ser acessada se o usuário estiver autenticado no sistema, basta você colocar o atributo “Authorize” no método (Figura 05). Caso todas as ActionResults (ou quaisquer outros métodos) sejam restritas, você pode colocar o atributo no Controller sem problemas.

Figura 05 – Utilização do atributo Authorize

Após uma breve explicação sobre o atributo “Authorize”, precisamos criar uma classe que realizará a comunicação entre o Controller e o RoleProvider. Para isso, clique com o direito na pasta “MembershipRoleProvider” e adicione uma nova classe chamada “Filtro”. Faça com que essa classe herde de “AuthorizeAttribute” que é a classe responsável pela configuração do “Authorize”. Em seguida, iremos sobreescrever o método “OnAuthorization” da classe “AuthorizeAttribute”. O código da classe “Filtro” encontra-se abaixo na Figura 06.

Figura 06 – Classe Filtro para comunicação do Controller com o RoleProvider

Próximo passo é dizermos que uma determinada ActionResult somente pode ser acessada por usuários com aquelas Roles/Permissões. No HomeController, criaremos uma ActionResult chamada “SomenteAdmin” e outra “TodosUsuarios” e com a definição de quais Roles/Permissões podem acessá-las (Figura 07).

Figura 07 – ActionResult com a definição de Roles permissionadas

Antes de testarmos a nossa aplicação, precisamos ainda de mais uma configuração. Precisamos informar ao Web.Config que utilizará o nosso RoleProvider (Figura 08). Perceba que deve o atributo “defaultProvider” (que será o Provider padrão da aplicação) possui como valor “ConfigProvider” que é a classe que criamos. Outra atenção especial é o atributo “type” que deve ser todo o namespace do valor configurado no atributo “defaultProvider”. O outro atributo configurável é o “name” que é o nome do RoleProvider.

Figura 08 – Configuração do RoleProvider no Web.Config

Se entrarmos no sistema, com o usuário “andre” e senha “1234”, e clicamos no menu “Somente Admin”, perceba que a página é demonstrada. Assim como, se clicarmos no menu “Usuarios”, a página também é mostrada (Figura 9).

Figura 09 – Mostrando que o usuário “andre” possui acesso à página SomenteAdmin

Vamos agora clicar em “Sair”, clicar novamente em “Entrar” e entrar com os dados: usuário “joao” e senha “4567”. Se você clicar no menu “Usuarios”, a página será mostrada. Entretanto, se você clicar no menu “Somente Admin”, perceba que você será redirecionado para a página de Acesso Negado (Figura 10). Lembrando que no banco de dados, falamos que o usuário “andre” tem as permissões/roles “Admin” e “Usuarios” e o usuário “joao” possui somente a permissão/role “Usuarios” cadastrada (O script SQL que acompanha o download do projeto possui os insert de exemplo).

Figura 10 – Mostrando que o usuário “andre” possui acesso à página SomenteAdmin

Quando uma ActionResult é marcada com o atributo Authorize ou faz uso de Roles/Users, o MVC primeiramente chama o método “OnAuthorization” para ver se o usuário possui acesso àquela página, respeitando as Roles que estão configuradas. Se colocarmos um breakpoint na classe “Filtro” e outro no método “GetRolesForUser”, perceba que o breakpoint atingirá a classe Filtro primeiramente, depois ele atingirá o “GetRolesForUser” para saber quais as roles/permissões do usuário e, por final, a classe Filtro continua a execução do seu código e com a resposta se o usuário pode acessar a página ou não, de acordo com a Role definida pela ActionResult.

Bom, pessoal mostrei a vocês neste longo artigo como podemos criar uma configuração de permissionamento através de Roles previamente determinadas ou estáticas. Estática que eu digo é que dificilmente o sistema modificará as roles cadastradas no banco ou hard-coded.

No próximo artigo, falarei como podemos criar uma configuração com Roles dinâmicas, ou seja, não existirão Roles fixadas no banco e nem hard-coded. Pense, por exemplo, em uma aplicação onde o administrador do sistema cria grupos de usuários para os seus funcionários e ele determina quais grupos de usuários podem acessar quais página. Mas, isso é uma outra estória que veremos daqui uns dias!

Download do projeto

Obrigado e até o próximo artigo!

André Miranda

@cypreste_andre

acymiranda@gmail.com