ASP.NET MVC permissions system

Asked

Viewed 1,079 times

4

A long time ago I developed a system, in ASP.NET MVC, where I used the package Mvcsitemapprovider, based on it I made some modifications in Authorizeattribute to perform the verification of user permissions.

On my Sitemap I made some additions, which were the Visibilities

0 - for Work Centre (Basically the system areas),

1 - for visions (Basically my controllers),

2 - for operations (actions) and

3 - not to display.

<mvcSiteMapNode title="Cidade" area="GRC" controller="Cidade" action="Index" visibilidade="1" key="5fdb0d96-1a21-4395-8868-e71c0ae061ec" >
                <mvcSiteMapNode title="Pesquisar" area="GRC" controller="Cidade" action="Index" visibilidade="2"  key="34d42538-d4cc-4091-a9cf-ab8b35326f62" />
                <mvcSiteMapNode title="Selecionar" area="GRC" controller="Cidade" action="Selecionar" visibilidade="3"  key="4146ff62-901f-4852-9084-a9c8434fc279" />
                <mvcSiteMapNode title="Inserir" area="GRC" controller="Cidade" action="Inserir" visibilidade="2"  key="02383e88-278b-4433-9960-b810866add30" />
                <mvcSiteMapNode title="Editar" area="GRC" controller="Cidade" action="Editar" visibilidade="3"  key="e5a58df4-4af8-428b-83d9-36e52a9f5ab3" />
                <mvcSiteMapNode title="Excluir" area="GRC" controller="Cidade" action="Excluir" visibilidade="3"  key="894c9fcf-8445-49dc-adac-bc6bde3b2986" />
            </mvcSiteMapNode>

Good base on this visibility I mounted dynamically my top menus, side and actions of a specific screen, basically having three Partialviews and a class to search in the database the menus that the user has permission

_Menucentrotrabalho

<link rel="stylesheet" href="@Url.Content("~/Content/Menu/superfish.css")" media="screen">
<link rel="stylesheet" href="@Url.Content("~/Content/Menu/superfish-vertical.css")" media="screen">
<script type="text/javascript" src="@Url.Content("~/Scripts/Menu/hoverIntent.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/Menu/superfish.js")"></script>
<script type="text/javascript">
    $(document).ready(function () {
        // initialise plugins
        $(function () {

        });
    });
</script>
<div class="clear">
    @Html.MvcSiteMap().SiteMapPath()
</div>
<div id="menu2">
    <ul class="sf-menu" id="centrotrabalho">

        @using Syns.MvcApplication.WebSite
        @{
            var keyCentroTrabalho = MySiteMap.GetKeyCentroTrabalho((MvcSiteMapProvider.MvcSiteMapNode)SiteMap.CurrentNode);
        }

        @foreach (var item in MySiteMap.CentroTrabalho())
        {
            if (keyCentroTrabalho == item.Key)
            {
            <li class="current" style="background-color: Silver;">@Html.ActionLink(@item.Title, @item.Action, @item.Controller, new { Area = @item.Area }, null)</li>         
            }
            else
            { 
            <li class="current">@Html.ActionLink(@item.Title, @item.Action, @item.Controller, new { Area = @item.Area }, null)</li>         
            }
        }
    </ul>
</div>

_Menuoperacoes

<script type="text/javascript">
    $(document).ready(function () {
        // initialise plugins
        $(function () {

        });
    });
</script>
<div>
    @using Syns.MvcApplication.WebSite
    @{
        var operacoes = MySiteMap.Operacoes();
    }
    @foreach (var item in operacoes)
    {
        if (SiteMap.CurrentNode.Key == item.Key)
        {
        <div style="margin-right: 5px; float: left;">
            @item.Title
        </div>
        }
        else
        {
        <div style="margin-right: 5px; float: left;">
            @Html.ActionLink(@item.Title, @item.Action, @item.Controller, new { Area = @item.Area }, null)
        </div>
        }
        if (operacoes.Last().Key != item.Key)
        {
        <div style="margin-right: 5px; float: left;">
            |
        </div>
        }

    }
</div>

_Menuvisoes

<link rel="stylesheet" href="/resources/demos/style.css" />
<script type="text/javascript">
    $(document).ready(function () {
        $(function () {
            $("#accordion").accordion();
        });
    });
</script>

<div id="menu2">
    <ul class="sf-menu sf-vertical sf-js-enabled" id="visoes">
        @using Syns.MvcApplication.WebSite
        @{
            string visaoKey = MySiteMap.GetKeyVisao((MvcSiteMapProvider.MvcSiteMapNode)SiteMap.CurrentNode);
        }
        @foreach (var item in MySiteMap.Visoes())
        {
            if (visaoKey == item.Key)
            {
            <li class="current" style="background-color: Silver;">@Html.ActionLink(@item.Title, @item.Action, @item.Controller, new { Area = @item.Area }, null)</li>         
            }
            else
            { 
            <li>@Html.ActionLink(@item.Title, @item.Action, @item.Controller, new { Area = @item.Area }, null)</li>         
            }
        }
    </ul>
</div>

Mysitemap

public static class MySiteMap
    {
        public static List<SiteMapModel> Menus()
        {
            List<SiteMapModel> menus = new List<SiteMapModel>();

            try
            {

                if (HttpContext.Current.Session["Menus"] != null)
                    menus = (List<SiteMapModel>)HttpContext.Current.Session["Menus"];
                else
                {
                    SiteMapServiceClient siteMapService = new SiteMapServiceClient();

                    if (UsuarioLogin != null)
                    {
                        UsuarioEntity usuario = new UsuarioBusiness().FindById(UsuarioLogin.UsuarioId);

                        menus = siteMapService.Menus(UsuarioLogin.UsuarioId);

                        if (menus.Count > 0)
                            HttpContext.Current.Session["Menus"] = menus;
                        else HttpContext.Current.Session["Menus"] = null;
                    }
                }

            }
            catch (Exception ex)
            {
                new SynsException(ex.Message, 0, ex);
            }

            return menus;
        }

        public static List<SiteMapModel> CentroTrabalho()
        {
            var menus = Menus().Where(a => a.Visibilidade == 0 && a.Parent.HasValue);

            List<SiteMapModel> itens = new List<SiteMapModel>();

            if (menus.Count() > 0)
            {
                itens = menus.ToList();
            }

            return itens;
        }

        public static List<SiteMapModel> Visoes()
        {
            string keyCentroTrabalho = GetKeyCentroTrabalho((MvcSiteMapNode)SiteMap.CurrentNode);

            var menus = Menus().Where(a => a.Visibilidade == 1 && a.KeyParent == keyCentroTrabalho);

            List<SiteMapModel> itens = new List<SiteMapModel>();

            if (menus.Count() > 0)
            {
                itens = menus.ToList();
            }

            return itens;
        }

        public static List<SiteMapModel> Operacoes()
        {
            string keyVisao = GetKeyVisao((MvcSiteMapNode)SiteMap.CurrentNode);

            var menus = Menus().Where(a => a.Visibilidade == 2 && a.KeyParent == keyVisao);

            List<SiteMapModel> itens = new List<SiteMapModel>();

            if (menus.Count() > 0)
            {
                itens = menus.ToList();
            }

            return itens;
        }



        public static string GetKeyVisao(MvcSiteMapNode node)
        {
            if (node == null)
                return "";

            if (node.Visibilidade != "1")
                return GetKeyVisao((MvcSiteMapNode)node.ParentNode);

            return node.Key;
        }

        public static string GetKeyCentroTrabalho(MvcSiteMapNode node)
        {
            if (node == null)
                return "";

            if (node.Visibilidade != "0")
                return GetKeyCentroTrabalho((MvcSiteMapNode)node.ParentNode);

            return node.Key;
        }


        private static UsuarioLoginEntity UsuarioLogin
        {
            get
            {
                if (HttpContext.Current != null && HttpContext.Current.Session.Count > 0
                    && HttpContext.Current.Session["Usuario"] != null
                    && HttpContext.Current.Session["Usuario"] is UsuarioLoginEntity)
                {
                    var temp = (UsuarioLoginEntity)HttpContext.Current.Session["Usuario"];

                    return temp;
                }


                return null;
            }
        }
    }

Even returning only the menus the user was allowed to, I did one more check using Authorizaattribute.

Myauthorize

public class MyAuthorize : AuthorizeAttribute
    {
        public MyAuthorize()
        {

        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext != null &&
                filterContext.HttpContext.Session.Count > 0 &&
                filterContext.HttpContext.Session["Usuario"] != null &&
                filterContext.HttpContext.Session["Usuario"] is UsuarioLoginEntity)
            {
                var temp = (UsuarioLoginEntity)filterContext.HttpContext.Session["Usuario"];

                var usuario = new UsuarioBusiness().FindById(temp.UsuarioId);
                if (usuario.MudarSenhaProximoLogin == true)
                    if (!filterContext.HttpContext.Request.RawUrl.Contains("Usuario/MudarSenha") && !filterContext.HttpContext.Request.RawUrl.Contains("Usuario/Sair"))
                    {
                        filterContext.Result = new RedirectResult("~/HCM/Usuario/MudarSenha");
                    }
            }

            base.OnAuthorization(filterContext);
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext != null &&
                httpContext.Session.Count > 0 &&
                httpContext.Session["Usuario"] != null &&
                httpContext.Session["Usuario"] is UsuarioLoginEntity)
            {
                var temp = (UsuarioLoginEntity)httpContext.Session["Usuario"];

                if (temp == null)
                    FormsAuthentication.SignOut();


                return VerificaPermissao(temp.UsuarioId);
            }

            return false;
        }

        private bool VerificaPermissao(int usuarioId)
        {
            //var siteMapKey = SiteMap.CurrentNode.Key;

            return true;
        }
    }

This works well, but now that I’m taking the course of ASP.NET MVC Module 1, offered by Gypsy, I am studying about ASP.NET Identity and with it emerged some new details, such as the use of Claims.

So I started to wonder, if there was a way to readjust my scenario with Claims?

This whole permission system came about because the system used at the time was already like this. Where users had their permissions based on menus and actions (CRUD) that they could or could not perform. This system was a Windows application.

So I started to wonder also, if for more complex systems developed in ASP.NET Mvc, if I should rethink my concept of permission?

Thus, the question arises, how to create a user permission system, where the "User A" has permission to register clients, the "User B" has permission to register and edit clients, the "User C" has permission to register, edit and delete clients, the "User ..." have permission to only view customers.

I can do this with Claims, or I have my concept of what I can do with Claims wrong?

1 answer

3


I can do this with Claims, or I have my concept of what I can do with Claims wrong?

In summary, yes. Let’s assume the following authorization attribute:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class ClaimsAuthorizeAttribute : AuthorizeAttribute
{
    private string claimType;
    private string claimValue;
    public ClaimsAuthorizeAttribute(string type, string value)
    {
        this.claimType = type;
        this.claimValue = value;
    }
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var user = filterContext.HttpContext.User as ClaimsPrincipal;
        if (user != null && user.HasClaim(claimType, claimValue))
        {
            base.OnAuthorization(filterContext);
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

And suppose the following decoration:

[ClaimsAuthorize("NivelTecnico", "Coordenador")]

What we do here is to check whether the current user is a coordinator or not. If it is, it must have permissions on the decorated element.

  • Based on your response, I would have to have a defined list of Claims and so I did, I have no roles and no set assignments, my permissions are directly user-based with the action. I try to decorate my controller only with [Myauthorize] without setting the Roles

  • This approach does not allow a parameterization, which may represent some penalty, especially in the example I presented.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.