Как перезагрузить пользовательский атрибут во время выполнения? ASP.NET Core MVC

У меня есть приложение, в котором пользователи могут создавать новые роли. Некоторые действия доступны только для определенных ролей. Чтобы проверить, разрешено ли пользователю выполнять определенное действие, я использую собственный атрибут AuthorizeAttribute, аналогичный https://stackoverflow.com/a/40300184.

[AuthorizeRoles(Permission.Unlink, Permission.Link)] 
[HttpGet("link")]
    public IActionResult Link(int id)
    {
        ...
    }

Класс AuthorizeRolesAttribute:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    public AuthorizeRolesAttribute(params Permission[] permissions)
    {   
        Roles = GetRoles(permissions);
    }
}

Получить роли:

public static string GetRoles(params Permission[] permissions)
{
    DataRowCollection rows = DatabaseHelper.RoleTable.Rows;
    List<string> allowedRoles = new List<string>();
    foreach (DataRow row in rows)
    {
        bool allowed = true;
        foreach (Permission permission in permissions)
        {
            if ((bool)row[permission.ToString()] == false)
                allowed = false;
        }
        //if all required permissions are true in this role it is added to the allowed roles
        if (allowed)
            allowedRoles.Add(row["ROLE"].ToString());
    }
    return string.Join(",", allowedRoles);
}

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

Я попытался запустить следующий код после добавления новой роли. (Как предложил https://stackoverflow.com/a/12196932)

typeof(UsersController).GetMethod(nameof(UsersController.Link)).GetCustomAttributes(false);

Это приводит к тому, что AuthorizeRolesAttribute снова вызывает GetRoles(), и это действительно возвращает строку с новой ролью в ней. Однако при попытке доступа к методу «Ссылка» в качестве пользователя с новой ролью я получаю статус 403 «Запрещено».

Тогда ваша проблема связана с кодом, который проверяет ваши роли.

Ian Kemp 26.04.2019 20:16

Однако уже существующие роли проверяются правильно. Кроме того, после перезапуска приложения новая роль проверяется корректно. Так что мне кажется, что метод GetRoles() работает нормально. Однако по какой-то причине атрибут AuthorizeRoles не действует соответствующим образом.

Chris 26.04.2019 20:40
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
241
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нашел решение. Вместо этого:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    public AuthorizeRolesAttribute(params Permission[] permissions)
    {   
        Roles = GetRoles(permissions);
    }
}

Теперь у меня есть это:

public class AuthorizeRolesAttribute : Attribute, IAuthorizationFilter 
{
    private readonly Permission[] permissions;
    public AuthorizeRolesAttribute(params Permission[] permissions)
    {
        this.permissions = permissions;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        string[] roles = Authentication.GetRoles(permissions).Split(",");
        bool allowed = context.HttpContext.User.Claims.Any(c => c.Type.Contains("role") && roles.Contains(c.Value));
        if (!allowed)
            context.Result = new ForbidResult();
    }
}

Другие вопросы по теме