Я хочу добавить авторизацию к контроллеру сразу для нескольких ролей.
Обычно это выглядит так:
[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}
Но я сохранил свои роли в константах, поскольку они могут измениться или быть расширены в какой-то момент.
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 и роль известны во время компиляции.
c#
asp.net-mvc
authorization
Кристиан Зауэр
источник
источник
Ответы:
Попробуйте создать собственный атрибут авторизации, подобный этому .
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)]
источник
System.Web.Http.AuthorizeAttribute
ВМЕСТОSystem.Web.Mvc.AuthorizeAttribute
Лучший и самый простой способ решить эту проблему - просто объединить роли в атрибуте Authorize.
[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]
с CustomRole - класс с такими постоянными строками:
public static class CustomRoles { public const string Admin = "Admin"; // and so on.. }
источник
То, что я сделал, - это ответ в @Tieson
Я немного подправил его ответ. Вместо string.Join, почему бы не преобразовать его в список?
Вот мой ответ:
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); } }
Вот и все, теперь он проверяет, авторизована ли роль для доступа к ресурсу.
источник
Мне кажется, что настраиваемый атрибут авторизации - излишний для этой проблемы, если у вас нет большого количества ролей.
Поскольку строка должна быть известна во время компиляции, почему бы не создать статический класс Role, содержащий общедоступные строки ролей, которые вы определили, а затем добавить строки, разделенные запятыми, с определенными ролями, которые вы хотите авторизовать:
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... } }
источник
ADMIN_OR_VIEWER
роль в действии является избыточной, потому что вам не будет разрешено получить доступ кCreate
методу, если у вас еще нетADMIN
роли. В этом случаеVIEWER
никогда не удастся вызватьCreate
метод.