Permissions system in ASP.NET MVC

4

I have long developed a system in ASP.NET MVC, where I used the MvcSiteMapProvider package, based on it I made some modifications to the AuthorizeAttribute to perform the user permissions check.

In my SiteMap I made some additions, which were Visibilities

0 - for Work Center (Basically the areas of the system),

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>

On the basis of this visibility I dynamically mounted my top, side, and screen menus, basically having three PartialViews and a class to fetch from the database the menus that the user is allowed to

_MenuCenterWork

<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>

_MenuOperations

<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>

_MenuVisions

<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 that the user was allowed to do, 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 fine, however now that I'm taking the #, offered by Cigano, I am studying ASP.NET Identity and with it came some new details such as the use of the Claims.

/ p>

So I started to wonder if there would be a way to readapt my scenario with Claims?

All this permission system came about because the system used at the time already be so. Where users had their Menu-Based and Actions-Allowed (CRUD) permissions they could or could not perform. This system was a Windows application.

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

In this way, creating a user permission system, where "User A" is allowed to register clients, "User B" is allowed to register and edit clients, "User C" is allowed to register, delete and delete clients, "User ..." is allowed to only view clients.

Can I do this with Claims, or am I getting my concept of what I can do with wrong Claims?

    
asked by anonymous 08.07.2016 / 13:42

1 answer

3
  

Can I do this with Claims, or am I getting my concept of what I can do with wrong Claims?

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.

    
12.07.2016 / 16:13