Авторизация атрибута с несколькими ролями
Я хотел бы добавить авторизацию к контроллеру, для нескольких ролей сразу.
обычно это выглядит так:
[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}
но я сохранил свои роли в consts, так как они могут измениться или быть расширены в какой-то момент.
public const RoleA = "RoleA";
public const RoleB = "RoleB";
public const RoleC = "RoleC";
Я не могу этого сделать, поскольку строка должна быть известна во время компиляции:
[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}
есть ли способ обойти эту проблему?
я мог бы написать константу, которая просто содержит "RoleA,RoleB,RoleC" - но я не люблю "Волшебные струны" и это волшебное слово. Изменение имени роли и забывание изменить объединенную строку было бы катастрофой.
Я использую MVC5. ASP.NET идентичность и роль известны во время компиляции.
5 ответов:
попробуйте создать пользовательский атрибут авторизации, например этой.
public class AuthorizeRolesAttribute : AuthorizeAttribute { public AuthorizeRolesAttribute(params string[] roles) : base() { Roles = string.Join(",", roles); } }
предполагая, что ваши роли будут одинаковыми для нескольких контроллеров, создать вспомогательный класс:
public static class Role { public const string Administrator = "Administrator"; public const string Assistant = "Assistant"; }
тогда используйте его так:
public class MyController : Controller { [AuthorizeRoles(Role.Administrator, Role.Assistant)] public ActionResult AdminOrAssistant() { return View(); } }
убедитесь, что вы производите свой пользовательский класс атрибутов от
System.Web.Mvc.AuthorizeAttribute
, а неSystem.Web.Http.AuthorizeAttribute
.я столкнулся с такой же проблемой. Как только я изменил его, все работало.
вы также можете добавить следующее в свой пользовательский класс атрибутов:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
не знаю, почему все приняли этот ответ. Я сделал именно так, как упоминалось, и теперь он абсолютно не проверяет авторизацию. Анонимные пользователи теперь могут подключаться к каждому методу, украшенному этим пользовательским атрибутом... Лучший и самый простой способ, который я нашел для решения этой проблемы, - это просто объединить роли в атрибуте Authorize.
[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]
С CustomRole класс с постоянными строками, как это:
public static class CustomRoles { public const string Admin = "Admin"; // and so on.. }
что я сделал ответ в @стяжек
Я немного подправляю его ответ. Вместо строки.Присоединяйтесь почему бы не преобразовать его в список?
вот мой ответ:
public class AuthorizeRolesAttribute : AuthorizeAttribute { private new List<string> Roles; public AuthorizeRolesAttribute(params string[] roles) : base() { Roles = roles.toList() } }
а затем проверить, если роль допустима переопределение OnAuthorization
public override void OnAuthorization(HttpActionContext actionContext) { if (Roles == null) HandleUnauthorizedRequest(actionContext); else { ClaimsIdentity claimsIdentity = HttpContext.Current.User.Identity as ClaimsIdentity; string _role = claimsIdentity.FindFirst(ClaimTypes.Role).Value; bool isAuthorize = Roles.Any(role => role == _role); if(!isAuthorize) HandleUnauthorizedRequest(actionContext); } }
и там у вас есть это, теперь он проверяет, если роль имеет право доступа к ресурсу
Я чувствую, что пользовательский атрибут авторизации является излишним для этой проблемы, если у вас нет большого количества ролей.
public static class Roles { public const string ADMIN = "Admin"; public const string VIEWER = "Viewer"; public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER; }
и затем вы можете использовать атрибут Authorize, например, в классе контроллера или методе контроллера (или оба):
[Authorize(Roles = Roles.ADMIN] public class ExampleController : Controller { [Authorize(Roles = Roles.ADMIN_OR_VIEWER) public ActionResult Create() { ..code here... } }