Динамически добавлять роли для авторизации атрибута для контроллера

Мне нужно разрешить моему администратору изменять права доступа для пользователей на лету, чтобы они могли создавать новые роли и добавлять разрешения к этим ролям.

Я хочу иметь возможность создать атрибут Authorize, который будет прикрепляться к моему классу контроллера, в который я могу добавлять роли из базы данных, чтобы мне не приходилось «устанавливать» роли во время разработки, как в [Authorize(Roles="Role1, Role2")] и т. Д.

Так что-то вроде [Authorize(Roles = GetListOfRoles()]

Я нашел этот вопрос - ASP.NET MVC Авторизовать пользователя со многими ролями который делает что-то подобное, но, возможно, есть способ изменить это так, чтобы он получал список разрешений / ролей из базы данных?


person barnacle.m    schedule 07.05.2015    source источник
comment
я полагаю, вам следует создать настраиваемого поставщика ролей. Но у вас должен быть список контроллеров и всех методов в db.   -  person teo van kot    schedule 07.05.2015


Ответы (2)


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

/// <summary>
/// Custom authorization attribute for setting per-method accessibility 
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class SetPermissionsAttribute : AuthorizeAttribute
{
    /// <summary>
    /// The name of each action that must be permissible for this method, separated by a comma.
    /// </summary>
    public string Permissions { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        SalesDBContext db = new SalesDBContext();
        UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
        ApplicationDbContext dbu = new ApplicationDbContext();

        bool isUserAuthorized = base.AuthorizeCore(httpContext);

        string[] permissions = Permissions.Split(',').ToArray();

        IEnumerable<string> perms = permissions.Intersect(db.Permissions.Select(p => p.ActionName));
        List<IdentityRole> roles = new List<IdentityRole>();

        if (perms.Count() > 0)
        {
            foreach (var item in perms)
            {
                var currentUserId = httpContext.User.Identity.GetUserId();
                var relatedPermisssionRole = dbu.Roles.Find(db.Permissions.Single(p => p.ActionName == item).RoleId).Name;
                if (userManager.IsInRole(currentUserId, relatedPermisssionRole))
                {
                    return true;
                }
            }
        }
        return false;
    }
}
person barnacle.m    schedule 21.05.2015
comment
как использовать SetPermissionsAttribute с методом действия? что мне нужно передать вместе с SetPermissionsAttribute ? - person Mou; 05.01.2017
comment
Прошло некоторое время, но если я правильно помню, это что-то вроде [SetPermissions="Action1, Action2"], но я не уверен. - person barnacle.m; 10.11.2017
comment
Всем следует принять к сведению, что это было некоторое время назад, и фактические запросы LINQ могут быть улучшены, а также следует внедрить контекст базы данных и диспетчер пользователей или внедрить репозиторий (при использовании шаблона репозитория). - person barnacle.m; 10.11.2017
comment
Просто мои чаевые в 2 цента, как правило, звонить в базу данных из атрибута - не лучшая идея. - person Tohid; 08.05.2018
comment
@Tohid, но как атрибут MVC Authorize по умолчанию проверяет вашу роль и т. Д., Не читая что-либо из базы данных? - person barnacle.m; 09.05.2018
comment
@ barnacle.m - мой комментарий (атрибуты лучше не называть db) был общим. Однако AuthorizeAttribute также не вызывает базу данных. В модели RBAC роли пользователя встраиваются в токен аутентификации при первой аутентификации пользователя. С этого момента доступ предоставляется путем сравнения ролей токенов с ролями, которые принимает метод, например Authorize("Admin"). Если принятая роль (в данном случае Admin) также является динамической и ее необходимо определить во время выполнения, я не знаю лучших практик в этом случае. - person Tohid; 12.05.2018

Как насчет чего-то вроде этого:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MyCustomAuthorizationAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        // Do some logic here to pull authorised roles from backing store (AppSettings, MSSQL, MySQL, MongoDB etc)
        ...
        // Check that the user belongs to one or more of these roles 
        bool isUserAuthorized = ....;

        if(isUserAuthorized) 
            return true;

        return base.AuthorizeCore(httpContext);
    }
}

Вы можете использовать его с базой данных или просто вести список авторизованных ролей в файле web.config.

person Mick Walker    schedule 07.05.2015
comment
Думаю, я знаю, к чему вы клоните, но ради других, кто может получить знания из этого вопроса, можете ли вы отредактировать свой ответ, чтобы сделать его более целостным (например, включить логику авторизации пользователя, возможно, также включите список IdentityRoles из базы данных в качестве примера), а затем я отмечу его как принятый. - person barnacle.m; 08.05.2015