如果我想只有管理員才能訪問名爲「ManagerUser」的動作,我知道我能做到這一點:ASP .NET MVC保護控制器/動作
[Authorize(Roles = Constants.ROLES_ADMINISTRATOR)]
public ActionResult ManageUser(string id)
{
}
如果我想給除了大家訪問管理員?我不想在函數中編寫所有角色:|。
任何建議/出路?
如果我想只有管理員才能訪問名爲「ManagerUser」的動作,我知道我能做到這一點:ASP .NET MVC保護控制器/動作
[Authorize(Roles = Constants.ROLES_ADMINISTRATOR)]
public ActionResult ManageUser(string id)
{
}
如果我想給除了大家訪問管理員?我不想在函數中編寫所有角色:|。
任何建議/出路?
您可以創建自己的自定義授權屬性,如「AuthorizeAllExceptAdmin」。在這個類中,你只需要檢查當前用戶是否是管理員,如果他們拒絕它,否則接受它。
這裏有一個很好的tutorial,但你可能會喜歡的東西最終會:
public class AuthorizeAllExceptAdmin : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return !httpContext.User.IsInRole(Constants.ROLES_ADMINISTRATOR);
}
}
那麼你的控制器的方法變爲:
[AuthorizeAllExceptAdmin]
public ActionResult SomethingOnlyNonAdminsCanDo()
{
}
下面是需要自定義屬性的示例角色否認。
public class DoNotAuthorize : AuthorizeAttribute
{
private IEnumerable<string> _rolesToReject;
public DoNotAuthorize(IEnumerable<string> rolesToReject)
{
_rolesToReject = rolesToReject;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
foreach (var role in _rolesToReject)
{
if (httpContext.User.IsInRole(role))
return false;
}
return true;
}
}
那麼你的控制器的方法變爲:
[DoNotAuthorize(new [] {Constants.ROLES_ADMINISTRATOR})]
public ActionResult SomethingOnlyNonAdminsCanDo()
{
}
我會考慮一些問題,它選擇上述選項之一之前。如果您認爲您將擁有多個具有類似授權要求的方法(或者整個控制器)(即管理員無法執行的多個操作),那麼我會堅持使用非參數化的自定義屬性。這樣,您可以稍後一起演變它們(僅更改自定義屬性)。例如,也許稍後您希望管理員能夠進入特殊模式,在這些模式下他們可以執行這些操作。或者,如果行動中的自動化程度更加不同,那麼使用參數化列表是有意義的,因爲它們將相對獨立地進化。
除了創建自定義AuthorizeAttribute,馬努建議,你可以使用的PrincipalPermission,有Deny-SecurityAction:
[PrincipalPermission(SecurityAction.Deny, Role="Administrator")]
在我的應用程序,所以我要查詢數據庫,以確定我不使用角色用戶是否有權訪問。以下代碼的好處是您可以非常輕鬆地將用戶重定向到某個操作。我在我的博客文章在http://blog.athe.la/2009/12/implementing-permission-via-windows-authentication-in-asp-mvc-using-action-filters/解釋代碼
public class DatabaseRepository()
{
private readonly DatabaseDataContext db = new DatabaseDataContext();
public bool UserHasPermission(string userLogon) {
return (from permission this.db.Permissions
where permission.HasPermissionSw == true
select permission).Contains(userLogon);
}
}
public class UserHasPermission: ActionFilterAttribute
{
private readonly DatabaseRepository databaseRepository = new DatabaseRepository();
private readonly string redirectAction;
public UserHasPermission(string redirectTo)
{
this.redirectAction = redirectTo;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string userLogon = filterContext.HttpContext.User.Identity.Name;
if (!this.databaseRepository.UserHasPermission(userLogon))
{
string routeController = filterContext.Controller.ControllerContext.RouteData.Values["controller"];
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = routeController, action = this.redirectAction }));
}
}
}
你的控制器,然後會是這個樣子:
[UserHasPermission("NoAccess")]
public ActionResult SecretArea()
{
// run all the logic
return View();
}
public ActionResult NoAccess()
{
return View();
}
任何意見;我怎麼能傳遞多個參數到自定義屬性?像[DoNotAuthorize(role ='A',role ='B')]? – effkay 2010-02-19 17:29:23
@effkay是的,你只需在構造函數中包含那些用於定製屬性的元素。我將在上面添加一個示例。 – manu08 2010-02-19 17:44:36
不錯的例子。使用IEnumerable,類似於我先前提出的IList。這樣你就可以擁有儘可能多的拒絕角色。 – 2010-02-20 16:52:38