Я хотел бы добавить авторизацию к контроллеру сразу для нескольких ролей.
Обычно это будет выглядеть так:
[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 и роль известны во время компиляции.
Ответ 1
Попробуйте создать настраиваемый атрибут авторизации, например .
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();
}
}
Ответ 2
Убедитесь, что вы выбрали свой собственный класс атрибутов System.Web.Mvc.AuthorizeAttribute
и NOT System.Web.Http.AuthorizeAttribute
.
Я столкнулся с той же проблемой. Как только я изменил его, все сработало.
Вы также можете добавить в свой собственный класс атрибутов следующее:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
Ответ 3
Лучший и самый простой способ, который я нашел для решения этой проблемы, это просто объединить роли в атрибуте Authorize.
[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]
с CustomRole класс с постоянными строками вроде этого:
public static class CustomRoles
{
public const string Admin = "Admin";
// and so on..
}
Ответ 4
Что я сделал, так это ответ в @Tieson
Я немного подправил его ответ. Вместо строки. Присоединяйтесь, почему бы не преобразовать его в список?
Вот мой ответ:
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);
}
}
И вот, у вас есть, теперь он проверяет, авторизована ли роль для доступа к ресурсу.
Ответ 5
Я чувствую, что специальный атрибут authorize является излишним для этой проблемы, если у вас нет большого количества ролей.
Так как строка должна быть известна во время компиляции, почему бы не создать статический класс ролей, который содержит общедоступные строки определенных вами ролей, а затем добавить строки, разделенные запятыми, с определенными ролями, которые вы хотите разрешить:
public static class Roles
{
public const string ADMIN = "Admin";
public const string VIEWER = "Viewer";
public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER;
}
И тогда вы можете использовать атрибут авторизации, например, в классе контроллера или методе контроллера (или обоих):
[Authorize(Roles = Roles.ADMIN]
public class ExampleController : Controller
{
[Authorize(Roles = Roles.ADMIN_OR_VIEWER)
public ActionResult Create()
{
..code here...
}
}
Ответ 6
То, что делает ответ Tieson, просто так =
[Authorize (Roles = "Role1, Role2")]
проверено, работает.