Использование магических строк дает вам гибкость в объявлении нескольких ролей в атрибуте Authorize (например, [Authorize (Roles = "Admin, Moderator")], которые вы склонны терять при переходе к строго типизированному решению. Но вот как вы может поддерживать эту гибкость, все еще получая все строго напечатано.
Определите свои роли в перечислении, которое использует битовые флаги:
[Flags]
public enum AppRole {
Admin = 1,
Moderator = 2,
Editor = 4,
Contributor = 8,
User = 16
}
Переопределить AuthorizeAttribute:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyAuthorizeAttribute : AuthorizeAttribute {
public AppRole AppRole { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext) {
if (AppRole != 0)
Roles = AppRole.ToString();
base.OnAuthorization(filterContext);
}
}
Теперь, если вы можете использовать MyAuthorizeAttribute следующим образом:
[MyAuthorize(AppRole = AppRole.Admin | AppRole.Moderator | AppRole.Editor)]
public ActionResult Index() {
return View();
}
Вышеуказанное действие авторизует только тех пользователей, которые хотя бы в одной из перечисленных ролей (Администратор, Модератор или Редактор). Поведение такое же, как и для AuthorizeAttribute по умолчанию в MVC, за исключением того, что без волшебных строк.
Если вы используете эту технику, вот метод расширения IPrincipal, который также может быть полезен:
public static class PrincipalExtensions {
public static bool IsInRole(this IPrincipal user, AppRole appRole) {
var roles = appRole.ToString().Split(',').Select(x => x.Trim());
foreach (var role in roles) {
if (user.IsInRole(role))
return true;
}
return false;
}
}
Вы можете использовать этот метод расширения следующим образом:
public ActionResult Index() {
var allowed = User.IsInRole(AppRole.Admin | AppRole.Moderator | AppRole.Editor);
if (!allowed) {
// Do Something
}
return View();
}