Атрибут Authorize с несколькими ролями
Я хотел бы добавить авторизацию к контроллеру для нескольких ролей сразу.
обычно это выглядит так:
[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}
но я сохранил свои роли в const, так как они могут измениться или быть расширены в какой-то момент.
public const RoleA = "RoleA";
public const RoleB = "RoleB";
public const RoleC = "RoleC";
Я не могу этого сделать, поскольку строка должна быть известна во время компиляции:
[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}
есть ли способ обойти эту проблему?
Я мог бы написать const, который просто содержит "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();
}
}
убедитесь, что вы выводите свой пользовательский класс атрибутов off 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...
}
}