ASP.NET MVC - 动态授权

14

我正在构建一个简单的CMS,其中角色是在管理员面板中动态设置的。现有的授权控制器方法的方式,例如添加[Authorize(Roles="admin")],因此已不再足够。角色与操作之间的关系必须存储在数据库中,以便最终用户可以轻松地在管理员面板中向其他用户授予/收回权限。如何实现这一点?

3个回答

20

如果你想控制授权过程,你应该继承 AuthorizeAttribute 并且重写 AuthorizeCore 方法。然后在你的控制器上使用你自己的 CmsAuthorizeAttribute 替代默认的即可。

public class CmsAuthorizeAttribute : AuthorizeAttribute
{
    public override virtual bool AuthorizeCore(HttpContextBase httpContext)
    {
        IPrincipal user = httpContext.User;
        IIdentity identity = user.Identity;

        if (!identity.IsAuthenticated) {
            return false;
        }

        bool isAuthorized = true;
        // TODO: perform custom authorization against the CMS


        return isAuthorized;
    }
}
这样做的缺点是您将无法访问通过构造函数注入的IoC,因此您必须直接从容器请求任何依赖项。

直接从容器中获取依赖项的缺点是什么?我不得不为我的RoleProvider实现这样做... - Haroon
1
@Haroon - 缺点在于设计。通常认为最佳实践是让代码保持对IoC容器的无知,以减少对其的依赖(例如,您可能希望在WP7上重用代码,在那里基于反射的容器通常会因性能原因而被避免)。 - Richard Szalay
@Haroon - 话虽如此,MVC 3支持通过属性装饰的属性进行过滤器属性注入。它仍然需要对容器有所了解,但更容易进行模拟。 - Richard Szalay
这就是我遇到的问题,有时候mvc2感觉很不专业,但我认为如果能通过容器完成工作,我宁愿不编写不专业的代码来实现“理想”的功能。 - Haroon

0

这正是ASP.NET会员/配置文件所能为您做的事情。而且它还可以与Authorize属性一起使用。

如果您想自行开发,您可以创建一个自定义操作过滤器来模仿标准的Authorize操作过滤器的行为。以下是伪代码示例。

public MyAuthorizeAttribute : ActionFilterAttribute
{
    public string MyRole { get; set; }

    public void OnActionExecuting(ControllerContext context)
    {
        if (!(bool)Session["userIsAuthenticated"])
        {
            throw new AuthenticationException("Must log in.");
        }

        if (!Session["userRoles"].Contains(MyRole))
        {
            throw new AuthenticationException("Must have role " + MyRole);
        }
    }
}

我对这方面还很新,但我看到了一个示例,在代码中特别指定了角色,我不想这样做。例如,某个客户可能有一个名为“工程师”的用户组,该用户组具有特定的权限。我希望他能够从管理员面板设置它们,而不需要更改任何代码。目前,我看不到如何使用标准的Authorize属性来实现这一点。 - xantrus
那么你将不得不在某个时候添加数据库查找,也许将用户和控制器/操作名称与您在数据库中拥有的访问规则匹配。或者类似的东西。 - rmac

0
角色-操作关系必须存储在数据库中。您需要在控制器方法中检查安全性,除非您想要子类化AuthorizeAttribute,以便它为您从数据库中查找角色。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接