Подтвердить что ты не робот

Авторизация на основе назначенной функции разрешения

У меня есть три таблицы  dbo.PermissionFunc, dbo.Roles, dbo.Permissions для моего asp.net MVC web application.

dbo.PermissionFunc содержит все имя функции в моем проекте. dbo.Roles содержит роли пользователя, такие как admin, user, subuser и т.д. dbo.Permissions содержит RolesId от dbo.Roles и PermissionFuncId от dbo.PermissionFunc. Я хочу дать authorization на основе значения, назначенного в dbo.Permission.

Изображение показывает назначающее разрешение роли

Обновление в вопросе: Запрос, чтобы определить, имеет ли текущий пользователь разрешение или нет

        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
        }

Заранее спасибо

4b9b3361

Ответ 1

Ответ, который работал над вышеуказанным вопросом, находится здесь:

AuthorizationController

#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

Foreact 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

Вы можете создать custom AuthorizationAttribute с логикой проверки своих ролей и разрешений в ней и использовать ее для операций, которые этого требуют.

Вы можете использовать mvc.filters с вашей реализацией IAuthorizationFilter для фильтрации каждого запроса. Зарегистрируйте его в своем FilterConfig

filters.Add(new MyAuthorizationAttribute());

Ответ 3

Обновлен для использования атрибута CustomAuthorize при действии MVC

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

Alsamil,

Если у вас есть время, прочитайте о том, как Microsoft делает Авторизация на основе претензий

И если у вас еще больше времени, я действительно рекомендую вам эту конференцию. Доминик Байер и Брок Аллен действительно известны в индустрии безопасности, и они объясняют, как сделать авторизацию в действительно хорошем виде, который связан с Авторизация на основе претензий статья. Если я не ошибаюсь, они являются умами этого нового способа авторизации.

Ответ 5

Кажется, что вы вводите в заблуждение авторизацию с созданием разных уровней доступа.

Он обращает внимание на детализацию и методическую обработку, чтобы гарантировать, что пользовательские роли, полученные путем аутентификации пользователя, затем управляются в рамках всего проекта, чтобы уровни разрешений поддерживались.

Роли необходимо проверять как внутри контроллера вида, так и всякий раз, когда данные передаются через входы View.

Один из способов сделать это - проверить, разрешен ли пользователь, то есть войти в систему.

Если пользователь авторизован, то проверьте роль пользователя в контроллере, который затем направит результат действия. Направляя пользователя в представление, соответствующее их уровням разрешений.

Информация может быть передана в представление через переменную ViewBag, так что некоторые функции включены или отключены в представлении в зависимости от роли (уровень разрешений). Хотя это нельзя полагаться только на одиночку, необходимо также разрешить серверные разрешения при любых запросах на изменение данных.

Например (это псевдокод):

if (user == null) return RedirectToRoute("home");

ViewBag.DisableInput = 0;

if (user.Role == Role.Admin)
    ViewBag.DisableInput = 1;

В представлении возьмите данные ViewBag.

var disableInput = ViewBag.DisableInput;

Используя JS, различные входы или поля вида могут быть скрыты или отключены.

if (@disableInput === 1) // todo

Итак, если нажать кнопку и данные будут изменены, снова необходимо проверить роль.
На стороне сервера, в качестве дополнительного уровня безопасности, необходимо проверить роль пользователя (следовательно, разрешения), когда любая информация, запрашивающая изменение, передается из представления. Один из способов - использовать контроллер API.

Проверять роли в контроллере API.

[HttpPost]
public int ApiAction(int id, FormDataCollection formData)
{
    try
    {
        var user = new //GetLoggedInUser();
        if (user == null)
            throw new Exception("Unauthorised access.");
        if (user.Role != Role.Admin) throw new Exception("Unauthorised access.");

        if (formData["mode"] == "put")
        {
            // Have your model or rules set up to process the information.
            return Model.blabla// do something
        }

Ответ 6

Вам нужно создать пользовательский атрибут 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;
    }
}