У меня есть приложение, в котором пользователи могут создавать новые роли. Некоторые действия доступны только для определенных ролей. Чтобы проверить, разрешено ли пользователю выполнять определенное действие, я использую собственный атрибут 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 «Запрещено».
Однако уже существующие роли проверяются правильно. Кроме того, после перезапуска приложения новая роль проверяется корректно. Так что мне кажется, что метод GetRoles() работает нормально. Однако по какой-то причине атрибут AuthorizeRoles не действует соответствующим образом.





Я нашел решение. Вместо этого:
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();
}
}
Тогда ваша проблема связана с кодом, который проверяет ваши роли.