【问题标题】:Authorization based on assigned Permission function基于分配的权限功能的授权
【发布时间】:2018-02-20 11:23:38
【问题描述】:

我有三张桌子 dbo.PermissionFunc, dbo.Roles, dbo.Permissions 我的asp.net MVC web application

dbo.PermissionFunc 包含我项目中的所有函数名称。 dbo.Roles 包含用户角色,如管理员、用户、子用户等 dbo.Permissions 包含来自dbo.RolesRolesId 和来自dbo.PermissionFuncPermissionFuncId。 我想根据dbo.Permission中分配的值给authorization

有问题的更新: 查询用于判断当前用户是否有权限

        string mail = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
        var usr = _user.GetUserByMail(mail);
        var permFunc = _permissionfunc.FindByName("ActionResultName");
        var permission = _permission.checkIfPermitted(Convert.ToInt64(usr.Usr_Role_ID), permFunc.PermFunc_ID);//usr.Usr_Role_ID is RoleId and permFunc.PermFunc_ID is the PermissionFunctionId
        if(permission != null)
        {
              //Permission granted
        }
        else
        {
             //Permission Rejected
        }

提前致谢

【问题讨论】:

  • 不确定你真正追求的是什么。根据描述,您似乎需要针对权限 ID 编写功能代码并调用通用可重用代码来评估登录用户通过角色解析的权限 ID,然后判断(隐藏/显示/只读等)可以是什么完成功能。
  • @Lin 我想根据dbo.Permission 中分配的值对函数进行授权。
  • 什么表将权限映射到函数 (dbo.PermissionFunc)?
  • 好的,您使用什么查询来确定当前用户是否具有特定的表和权限 - 例如,如果用户导航到 TaxControllerEdit() 方法? (至少应该包含在您的问题中,以便答案中的代码有意义)
  • 自定义 AuthorizationAttribute 不合适(用户已获得授权,如果他们没有特定操作的权限,您不希望他们再次登录)。您当然可以添加代码来检查每个控制器方法中的权限,但使用 ActionFilter 会是更好的选择。

标签: c# sql-server asp.net-mvc web-applications


【解决方案1】:

对上述问题有效的答案在这里:

授权控制器

#region CustomAuthorizationAttribute
public class CustomAuthorizationAttribute : AuthorizeAttribute
{

    private PermissionRepository _permission = new PermissionRepository();
    private PermissionFuncRepository _permissionFun = new PermissionFuncRepository();


    // roles start
    public string IdentityRoles
    {
        get { return _permissionName ?? String.Empty; }
        set
        {
            _permissionName = value;
        }
    }

    private string _permissionName;

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        //do the base class AuthorizeCore first

        if (httpContext.User.Identity.IsAuthenticated)
        {
            string RoleID = FormsAuthentication.Decrypt(httpContext.Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name.Split('|')[1];
            var permisionID = _permissionFun.FindByName(_permissionName);
            if(permisionID != null)
            {
                var permis = _permission.GetPermission().Where(a => a.Perm_PermFuncID == permisionID.PermFunc_ID && a.Perm_RollID.ToString() == RoleID).FirstOrDefault();
                if (permis != null)
                {
                    return true;
                }
            }
        }
        return false;

    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        //if the user is not logged in use the deafult HandleUnauthorizedRequest and redirect to the login page
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
        else
        //if the user is logged in but is trying to access a page he/she doesn't have the right for show the access denied page
        {
            filterContext.Result = new RedirectResult("~/Home/AccessDenied");
        }
    }


}
#endregion

Foreach ActionController,我访问这些授权如下:

    [CustomAuthorization(IdentityRoles = "AdjustmentsView")]
    public ActionResult AdjustmentIndex()
    {
        var adjlist = _Adj.GetAdjustmentHead();
        List<AdjustmentHeadViewModel> adjustlist = new List<AdjustmentHeadViewModel>();
        foreach (var item in adjlist)
        {
            Mapper.Initialize(cfg => cfg.CreateMap<AdjustmentHead, AdjustmentHeadViewModel>());
            AdjustmentHeadViewModel entity = Mapper.Map<AdjustmentHead, AdjustmentHeadViewModel>(item);
            adjustlist.Add(entity);
        }
        return View(adjustlist);
    }

【讨论】:

    【解决方案2】:

    您需要创建一个自定义 AuthorizeAttribute 并用它标记您的操作。

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class RequireFunction : AuthorizeAttribute
    {
        private string _function;
    
        public RequireFunction(string func) { _function = func; }
    
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext.User == null)
                return false;
    
            if (!httpContext.User.Identity.IsAuthenticated)
                return false;
    
            // modified code sample from question
            string mail = httpContext.User.Identity.Name;
            var user = _user.GetUserByMail(mail);
            var permFunc = _permissionfunc.FindByName(_function);
            var permission = _permission.checkIfPermitted(Convert.ToInt64(usr.Usr_Role_ID), permFunc.PermFunc_ID);
            return permission != null;
        }
    }
    

    【讨论】:

    • 已发布解决方案。有需要请参考。
    【解决方案3】:

    更新为在 MVC 操作上使用 CustomAuthorize 属性

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class CustomAuthorize : AuthorizeAttribute
    {
        private string _action { get; set; }
    
        public CustomAuthorize() { }
        public CustomAuthorize(string action) { _action = action; }
    
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext.User == null)
                return false;
    
            if (!httpContext.User.Identity.IsAuthenticated)
                return false;
    
            // HasPermission function implements looking up by user name and action
            // to see if user has a role that would give them access to this action
            return PermissionChecker.HasPermission(httpContext.User.Identity.Name, _action);
        }
    
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            // handle unauthorized requests here
            // return 503 error or whatever
        }
    
    }
    
    
    // example of using custom attribute in MVC controller action
    [HttpGet]
    [CustomAuthorize("View")]
    public ActionResult MyActionActualViewMethodName()
    {
        var result = {
            id = 1,
            name = ""
        };
        return Json(result);
    }
    
    [HttpDelete]
    [CustomAuthorize("Delete")]
    public ActionResult MyActionActualDeleteMethodName(int id)
    {
        // do delete action
        return Json(true);
    }
    
    
    // static permission checker implementation    
    public static class PermissionChecker
    {
        static List<GenericIdNameClass> users = new List<GenericIdNameClass>() {
            new GenericIdNameClass { Id = 1, Name = "John" },
            new GenericIdNameClass { Id = 2, Name = "Bob" },
        };
    
        static List<GenericIdNameClass> roles = new List<GenericIdNameClass>() {
            new GenericIdNameClass { Id = 10, Name = "User" },
            new GenericIdNameClass { Id = 11, Name = "Admin" },
        };
    
        static List<GenericIdNameClass> actions = new List<GenericIdNameClass>() {
            new GenericIdNameClass { Id = 100, Name = "View" },
            new GenericIdNameClass { Id = 101, Name = "Create/Edit" },
            new GenericIdNameClass { Id = 102, Name = "Delete" },
        };
    
        static List<GenericEntityRelationClass> roleActionMappings = new List<GenericEntityRelationClass>() {
            new GenericEntityRelationClass{ Id1 = 10, Id2 = 100 },
            new GenericEntityRelationClass{ Id1 = 11, Id2 = 100 },
            new GenericEntityRelationClass{ Id1 = 11, Id2 = 101 },
            new GenericEntityRelationClass{ Id1 = 11, Id2 = 102 },
        };
    
        // John only has User role, Bob has User and Admin
        static List<GenericEntityRelationClass> userRoleMappings = new List<GenericEntityRelationClass>() {
            new GenericEntityRelationClass{ Id1 = 1, Id2 = 10 },
            new GenericEntityRelationClass{ Id1 = 2, Id2 = 10 },
            new GenericEntityRelationClass{ Id1 = 2, Id2 = 11 },
        };
    
        public static bool HasPermission(string userName, string actionName)
        {
            var user = users.SingleOrDefault(x => x.Name == userName);
            if (user == null)
                return false;
    
            var action = actions.SingleOrDefault(x => x.Name == actionName);
            if (action == null)
                return false;
    
            var userRoles = userRoleMappings.Where(x => x.Id1 == user.Id).Select(x => x.Id2).ToList();
    
            return roleActionMappings.Any(x => userRoles.Contains(x.Id1) && x.Id2 == action.Id);
        }
    
        public class GenericIdNameClass
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    
        public class GenericEntityRelationClass
        {
            public int Id1 { get; set; }
            public int Id2 { get; set; }
        }
    }
    

    【讨论】:

    • 感谢您的尝试。但这不是我问题的答案。角色分配已经完美运行。我想要基于分配的角色和权限的授权。
    • 已发布解决方案。有需要可以参考。
    【解决方案4】:

    阿尔萨米尔,

    如果你有时间,请阅读微软的新方式Claims-Based Authorization

    如果你有更多的时间,我真的推荐你this会议。 Dominick Baier 和 Brock Allen 在安全行业中非常有名,他们解释了如何以非常好的方式进行授权,这与 Claims-Based Authorization 文章相关。如果我没记错的话,他们就是这种新的授权方式背后的思想。

    【讨论】:

    • 已发布解决方案。有需要可以参考。
    【解决方案5】:

    您可以创建custom AuthorizationAttribute,其中包含检查您的角色和权限的逻辑,并将其用于需要的操作。

    您可以将mvc.filtersIAuthorizationFilter 的实现一起使用,以过滤每个请求。注册到你的FilterConfig

    filters.Add(new MyAuthorizationAttribute());
    

    【讨论】:

    • 有一个授权功能。我如何从控制器访问每个 ActionResult 的该函数
    • 您可以使用 mvc.filters 和 IAuthorizationFilter 的实现来过滤每个请求
    猜你喜欢
    • 1970-01-01
    • 2012-05-07
    • 2015-01-18
    • 2021-09-14
    • 2019-12-08
    • 1970-01-01
    • 2022-09-28
    • 2015-11-06
    • 2021-04-01
    相关资源
    最近更新 更多