MVC 3 динамическое разрешение нескольких ролей и пользователей
Недавно я занимался разработкой MVC 3, но с тех пор у меня есть опыт работы как на С#, так и на ASP.NET. Поэтому я начну с того, что я пытаюсь выполнить. Я разработал небольшой сайт для размещения статей. Я внедрил управление сайтом на основе SQLServer на сайт. Теперь я хочу создать систему учетных данных, которая ограничивает и позволяет правильным пользователям создавать, удалять и обновлять статьи. Для этого есть одно простое решение: сделать это следующим образом:
[Authorize(Roles="Admin")]
public ActionResult UpdateArticle(ArticleModel model, int articleid)
{
return View();
}
Теперь это действительно просто. Я просто говорю, что только членам, находящимся в роли "Admin", разрешено обновлять статью. Но это только статично. Поэтому я создал таблицу учетных данных в моей базе данных, которая в конце говорит мне, что "Статья 5 может быть отредактирована ролями 1,2,3 и 4 и пользователями A, b и C". Все идет нормально. Но как я могу реализовать это с помощью разрешения Authorize?
Я хотел бы сделать что-то вроде этого:
[Authorize(getAuthorizedusers("update",this.articleid))]
где getAuthorizedusers возвращает, какие пользователи и роли имеют право обновлять статью с переданной ей статьей.
Итак, у меня есть (по крайней мере) две проблемы:
-Удаление метода авторизации для приема нескольких пользователей и ролей.
-Пассирование поставляемого изделия, которое было отправлено методу UpdateArticle, методу getAuthorizedusers.
Ответы
Ответ 1
Вы можете создать свой собственный пользовательский атрибут, который наследует от AuthorizeAttribute
и переопределить метод OnAuthorize
, чтобы сделать то, что вам нужно.
Это должно помочь вам:
public class ArticleAuthorizeAttribute : AuthorizeAttribute
{
public enum ArticleAction
{
Read,
Create,
Update,
Delete
}
public ArticleAction Action { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
//do custom authorizization using Action and getting ArticleID
//from filterContext.HttpContext.Request.QueryString or
//filterContext.HttpContext.Request.Form
}
}
Использование будет выглядеть так:
[ArticleAuthorize(Action=ArticleAuthorizeAttribute.ArticleAction.Update)]
Изменить: посмотрев на это немного больше, похоже, что вы не можете передать this.articleID в атрибут. Однако у вас есть доступ к параметрам из filterContext.HttpContext.Request
через свойство QueryString
или свойство Form
, в зависимости от того, как вы передаете значения. Я обновил образец кода соответствующим образом.
Более полный пример можно найти здесь
Чтобы проверить авторизацию с использованием роли пользователя и списка пользователей, вы должны сделать что-то вроде этого:
var allowedUsers = new List<string>();
//populate allowedUsers from DB
If (User.IsInRole("Update") || allowedUsers.Contains(User.Identity.Name))
{
//authorized
}
В качестве альтернативы вы можете выполнять обе проверки с помощью БД непосредственно в одном методе, чтобы не выполнять два вызова.
Ответ 2
Здесь намного проще выполнить одно и то же:
[Authorize]
public ActionResult UpdateArticle(ArticleModel model, int articleid)
{
// if current user is an article editor
return View();
// else
return View("Error");
}
Ответ 3
Я получил его работу, как мне хотелось, когда я переопределил метод AuthorizeCore и разрешил способ, которым я хочу.
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
IPrincipal user = httpContext.User;
if (!user.Identity.IsAuthenticated)
{
return false;
}
if ((_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) && (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)))
{
return false;
}
return true;
}