ASP .NET Core 3.1 - Usando o Identity de cabo a rabo - XVIII


Hoje vamos continuar a série de artigos mostrando como usar o ASP .NET Core Identiy na versão 3.1 da ASP .NET .Core e do EF Core.

Continuando a décima sétima parte do artigo veremos como excluir uma role existente.

Exibindo o menu com base no perfil do usuário

Atualmente para poder exibir as roles estamos acessando manualmente digitando o caminho administration/listroles na url.

Vamos então definir que se a role de  um usuário for a role Admin então vamos exibir na barra de navegação o menu Gerenciar Roles, caso contrário não vamos exibir esta opção.

A barra de navegação esta definida no arquivo _Layout.cshtml do projeto e para poder verificar se um usuário esta logado e pertence a uma role teremos que usar o serviço SignInManager e os métodos IsSignedIn() e IsInRole().

Para isso vamos usar o recurso de injetar o serviço SingInManager na view _Layout.cshtml usando a diretiva @inject;  assim a diretiva Inject que permite injetar as dependências diretamente na View e recuperar os dados.

Como esse recurso já foi incluído na view _Layout.cshtml somente vamos verificar se o usuário faz parte do perfil Admin.

              ...
              <div class="collapse navbar-collapse" id="collapsibleNavbar">
                    <ul class="navbar-nav ml-auto">
                        @*Se o usuário esta logado exibir o link de logout*@
                        @if (SignInManager.IsSignedIn(User))
                        {
                            <li class="nav-item">
                                <form method="post" asp-controller="account" asp-action="logout">
                                    <button type="submit" style="width:auto"
                                            class="nav-link btn btn-link py-0">
                                        Logout @User.Identity.Name
                                    </button>
                                </form>
                            </li>
                            @if (User.IsInRole("Admin"))
                            {
                                <li class="nav-item">
                                    <a class="nav-link" asp-controller="Administration" asp-action="ListRoles">
                                        Gerenciar Roles
                                    </a>
                                </li>
                            }
                        }
                        else
                        {
                            <li class="nav-item">
                                <a class="nav-link" asp-controller="account" asp-action="register">
                                    Registrar
                                </a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" asp-controller="account" asp-action="login">
                                    Login
                                </a>
                            </li>
                        }
                    </ul>
                </div>
          ...

Agora o menu Gerenciar Roles será exibido quando o usuário pertencer à role Admin.

Mas e se o usuário digitar /administration/listroles na url ?

Como impedir esse tipo de acesso ?

Para isso vamos implementar a autorização usando o atributo Authorize e especificar a role que pode ter acesso ao recurso que desejamos.

Para fazer isso basta definir em um controlador ou método Action o atributo Authorize e especificar o perfil que terá acesso usando Roles :  Ex: Authorize(Roles="Admin,Teste,...")

Assim no controlador AdministrationController vamos definir o atributo Authorize e também especificar que somente usuários logados e que pertençam ao perfil Admin poderão ter acesso aos métodos Action :

    [Authorize(Roles="Admin")]
    public class AdministrationController : Controller
    {
        private readonly RoleManager<IdentityRole> roleManager;
        private readonly UserManager<ApplicationUser> userManager;
        public AdministrationController(RoleManager<IdentityRole> roleManager,
            UserManager<ApplicationUser> _userManager)
        {
            this.roleManager = roleManager;
            userManager = _userManager;
        }
        ....
    }

Agora, se qualquer usuário que não faça parte da role Admin tentar acessar o controlador AdminstrationController ele será direcionado para /Account/AccessDenied. Este é o comportamento padrão da ASP .NET Core.

Podemos alterar este comportamento no método ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
   ...
    services.ConfigureApplicationCookie(options =>
    {
        options.AccessDeniedPath = new PathString("xxxx/AccessDenied");
    });
}

Mas vamos deixar como estar e vamos usar o comportamento padrão.

Assim temos que criar no controlador AccountController o método Action AccessDenied

        [HttpGet]
        [AllowAnonymous]
        public IActionResult AccessDenied()
        {
            return View();
        }

Note que tivemos que definir o atributo [AllowAnonymous] para que o método possa ser acessado por usuários não autenticados.

Agora vamos criar a view  AccessDenied.cshtml para exibir quando o usuário for direcionado para este método Action:

<div class="text-center">
   <h3 class="text-danger">Acesso Negado</h3>
   <h4 class="text-danger">
        Você não tem permissão para usar este recurso
    </h4>
    <img src="~/images/semacesso.jpg" style="height:250px; width:200px" />
</div>

Para exibir a imagem usada nesta view vamos criar a pasta images dentro da pasta wwwroot e incluir nesta pasta a imagem semacesso.jpg.

Agora é só alegria...

Testando o projeto vamos usar o usuário com perfil admin e a seguir um usuário normal e depois vamos tentar acessar manualmente o controlador AdministrationController.

Abaixo temos o resultado:

No próximo artigo vamos exibir todos os usuários cadastrados.

Pegue o projeto aqui:  IdentityTotal_GerenciaRoles.zip (sem as referências)

"(Disse Jesus) - Quem ama a sua vida perdê-la-á, e quem neste mundo odeia a sua vida, guardá-la-á para a vida eterna."
João 12:25

Referências:


José Carlos Macoratti