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

У меня есть приложение, в котором пользователи могут создавать новые роли. Некоторые действия доступны только для определенных ролей. Чтобы проверить, разрешено ли пользователю выполнять определенное действие, я использую пользовательский атрибут 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);
    }
}

GetRoles:

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 Запрещено.

1 Ответ

0 голосов
/ 29 апреля 2019

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

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();
    }
}
...