Search code examples
asp.netasp.net-mvc-3entity-framework-4user-management

tiny custom role management for asp.net mvc 3


I chose to do a school project with asp.net mvc3 and there is a need of a user/role management. I think the membership that ships with asp.net is way too big for a school projec. SO my thought is this. if i could find an equivalent of Zend predispatch method for asp or even a better one i could store the urls accessible as privilege for a role and load it in session and check if a particular user have access to it and redirect if not.

my question are this:

Is there any equivalent of PreDispatch method in asp?
Is there any better approach for my problem ? if yes please post resources

Thanks for reading this

EDIT i generate sublinks from databse using this:

 public static class SubMenuHelper
{


    public static MvcHtmlString GetSubMenu()
    {
        var db = new SchoolContextExpress();
        var submenu = from s in db.Disciplines select s;
        var sbuilder = new StringBuilder();
        foreach (var discipline in submenu)
        {
            sbuilder.AppendFormat("<li><a class='sublink' href='/Discipline/Details/{0}'>{1}</a></li>", discipline.DisciplineID, discipline.Name);
        }
        return new MvcHtmlString(sbuilder.ToString());
    }
}

Solution

  • You can implement like this.

    1. Enum for roles
    2. FilterAttribute
    3. Create Web.sitemap for menu
    4. Add Menu creator action
    5. Add Menu to _Layout.cshtml
    6. Add FilterAttribute to controller or action

    ----1 Enum------

    public enum Roles{
         Common=1,
         Student = 2,
         Teacher=4
         Administration=8
    }
    

    ----2 RequirePermissionFilter----

    public class RequirePermissionFilter : ActionFilterAttribute, IAuthorizationFilter
    {
    
          private readonly Roles[] _requiredRoles;
           public RequirePermissionFilter(Roles requiredRoles)
        {
            _requiredRoles = new Roles[] { requiredRoles };
        }
    
        public RequirePermissionFilter(Roles[] requiredRoles)
        {
            _requiredRoles = requiredRoles;
        }
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            var success = false;
    
            foreach (Roles role in _requiredRoles)
            {
                 success |= _authManager.HasPermission(role);
            }
    
            if (success)
            {
                var cache = filterContext.HttpContext.Response.Cache;
                cache.SetProxyMaxAge(new TimeSpan(0));
                cache.AddValidationCallback((HttpContext context, object data, ref HttpValidationStatus validationStatus) =>
                {
                    validationStatus = this.OnCacheAuthorization(new HttpContextWrapper(context));
                }, null);
            }
            else
            {
                this.HandleUnauthorizedRequest(filterContext);
            }
        }
        private void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            // Ajax requests will return status code 500 because we don't want to return the result of the
            // redirect to the login page.
            if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new HttpStatusCodeResult(500);
            }
            else
            {
                filterContext.Result = new RedirectToRouteResult("Error - 401", null);
            }
        }
        public HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext)
        {
            var success = false;
    
            foreach (Roles role in _requiredRoles)
            {
                success |= _authManager.HasPermission(role);
            }
    
            if (success)
            {
                return HttpValidationStatus.Valid;
            }
            else
            {
                return HttpValidationStatus.IgnoreThisRequest;
            }
        }
    }
    

    ----3 Web.sitemap-----

    <?xml version="1.0" encoding="utf-8" ?>
    <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
        <siteMapNode url="" roleName="" title="" menuVisible="True">
            <siteMapNode url="~/Home/Index" roleName="-1" title="Home" menuVisible="True"/>
            <siteMapNode url="~/Student/Index" roleName="2 title="Student" menuVisible="True">
                 <siteMapNode url="~/MyLessons/Index" roleName="2 title="My Lessons" menuVisible="True"/>
            </siteMapNode>
            <siteMapNode url="~/Teacher/Index" roleName="4 title="Teacher" menuVisible="True"/>
            <siteMapNode url="~/Administration/Index" roleName="8 title="Administration" menuVisible="True"/>
        </siteMapNode>
    </siteMap>
    

    ----4 Menu Creator Action----

    public class CommonController : Controller{
    
        public ActionResult NavigationMenu()
            {
                return Content(SiteMapMenu());
            }
            public string SiteMapMenu()
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("<div class='menu'><ul>");
                var topLevelNodes = SiteMap.RootNode.ChildNodes;
    
    
                foreach (SiteMapNode node in topLevelNodes)
                {
                    if (HasPermission(node) && IsVisible(node))
                    {
                        if (SiteMap.CurrentNode == node)
                            sb.Append("<li class='selectedMenuItem'>");
                        else
                            sb.Append("<li>");
    
                        if (!string.IsNullOrEmpty(node.Url))
                            sb.AppendFormat("<a href='{0}'>{1}</a>", Url.Content(node.Url), node.Title);
                        else
                            sb.AppendFormat("<a href='javascript:void(0)'>{0}</a>", node.Title);
                        if (node.HasChildNodes && AnyOfChildIsVisible(node))
                        {
    
                            foreach (SiteMapNode childNode in node.ChildNodes)
                            {
                                if (HasPermission(childNode) && IsVisible(childNode))
                                {
                                    sb.Append("<li>");
                                    sb.AppendFormat("<a href='{0}'>{1}</a>", Url.Content(childNode.Url), childNode.Title);
                                    sb.Append("</li>");
                                }
                            }
    
                            sb.Append("</ul></div>");
                        }
    
                        sb.AppendLine("</li>");
                    }
                }
                sb.AppendLine("</ul></div>");
                return sb.ToString();
            }
            private bool HasPermission(SiteMapNode node)
            {
                int roleName = int.Parse(node["roleName"].ToString());
                if ((roleName == -1) || (_authManager.HasPermission((Roles)roleName)))
                    return true;
                return false;
            }
            private bool IsVisible(SiteMapNode node)
            {
                return bool.Parse(node["menuVisible"]);
            }
    
            private bool AnyOfChildIsVisible(SiteMapNode node)
            {
                foreach (SiteMapNode item in node.ChildNodes)
                {
                    if (IsVisible(item))
                        return true;
                }
                return false;
            }
    }
    

    ----5 Add helper to _Layout.cshtml

      @Html.Action("NavigationMenu", "Common")
    

    ----6 Controller----

    [RequirePermissionFilter(Roles.Student)]
    public class StudentController : Controller{
       /*
        *
        *
        *
        *
        */
    
    }
    

    ----AuthManager---

    public interface IAuthManager
    {
    
    
        bool HasPermission(Roles requiredRole);
    }
    
    public class AuthManager : IAuthManager
    {
        private ISessionManager _sessionManager;
        private ISuggestionConfig _config;
    
        public bool HasPermission(Roles requiredRoles)
        {
            if (HttpContext.Current.Session["USER"] != null)
                return (requiredRoles & ((User)HttpContext.Current.Session["USER"]).Roles) == requiredRoles;
            else
                return false;
        }
    }