ASP .NET MVC保护控制器/动作

时间:2010-02-19 16:57:08

标签: asp.net-mvc security

如果我只想让管理员访问名为“ManagerUser”的操作,我知道我可以这样做:

[Authorize( Roles = Constants.ROLES_ADMINISTRATOR )]
public ActionResult ManageUser( string id )
{
}

如果我想让除了管理员以外的所有人都可以访问该怎么办?我不想在函数上编写所有角色:|。

任何建议/出路?

3 个答案:

答案 0 :(得分:11)

您可以创建自己的自定义授权属性,例如“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() 
{ 
} 

在选择上述选项之一之前,我会考虑一下。如果你认为你有几个具有类似授权要求的方法(或整个控制器)(即管理员无法执行的几个操作),那么我会坚持使用非参数化的自定义属性。这样,您可以稍后将它们一起进化(仅通过更改自定义属性)。例如,稍后您可能希望管理员能够进入可以执行这些操作的特殊模式。

或者,如果动作之间的自动化程度更加不同,那么使用参数化列表是有意义的,因为它们将相对独立地发展。

答案 1 :(得分:5)

除了创建manu建议的自定义AuthorizeAttribute之外,您还可以使用带有Deny-SecurityAction的PrincipalPermission:

[PrincipalPermission(SecurityAction.Deny, Role="Administrator")]

答案 2 :(得分:1)

在我的应用程序中,我不使用角色,因此我必须查询数据库以确定用户是否具有访问权限。以下代码的好处是您可以非常轻松地将用户重定向到某个操作。我在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();
}
相关问题