如何为角色以及特定用户使用自定义授权属性?

Posted

技术标签:

【中文标题】如何为角色以及特定用户使用自定义授权属性?【英文标题】:How to use custom Authorize attribute for roles as well as a specific user? 【发布时间】:2012-07-14 16:26:00 【问题描述】:

我有我的行动方法

[Authorize(Roles="Admin")]
public ActionResult EditPosts(int id)

    return View();

在我的情况下,我需要授权管理员以便他们可以编辑帖子,但是(这里是很酷的部分),我还需要允许帖子的创建者能够编辑作为普通用户的帖子。那么如何过滤掉创建帖子的用户以及管理员,但让其他人未经授权?我收到 PostEntry id 作为路由参数,但这是在属性之后,并且属性只接受常量参数,看起来非常困难,非常感谢您的回答,干杯!

【问题讨论】:

因为您可能不知道是谁创建了帖子,直到您查找它。在水合对象后包含此逻辑可能会更好。否则,如果您将其作为方面实现,您可能需要查找帖子两次(一次用于授权,一次用于编辑)。 说得好,如果他的 id 在角色条目上,我确实会查找一次,然后再次执行我的控制器逻辑。任何想法如何只访问数据库一次? 多考虑一下,如果您使用的是好的 ORM,并在授权调用之前设置上下文(不确定那部分),那么它应该缓存在第一级缓存中。那么,你不应该认为第二个水合物会受到影响。 我确实在使用 Entity Framework 4.0,但我认为它没有任何问题。 【参考方案1】:

你可以写一个自定义的授权属性:

public class AuthorizeAdminOrOwnerOfPostAttribute : AuthorizeAttribute

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        
            // The user is not authenticated
            return false;
        

        var user = httpContext.User;
        if (user.IsInRole("Admin"))
        
            // Administrator => let him in
            return true;
        

        var rd = httpContext.Request.RequestContext.RouteData;
        var id = rd.Values["id"] as string;
        if (string.IsNullOrEmpty(id))
        
            // No id was specified => we do not allow access
            return false;
        

        return IsOwnerOfPost(user.Identity.Name, id);
    

    private bool IsOwnerOfPost(string username, string postId)
    
        // TODO: you know what to do here
        throw new NotImplementedException();
    

然后用它装饰你的控制器动作:

[AuthorizeAdminOrOwnerOfPost]
public ActionResult EditPosts(int id)

    return View();

【讨论】:

为什么 // 现在指定了 id => 我们不允许访问 ? 现在我明白了您需要更改:// 现在指定了 idNO 指定了 id.. ..(似乎如果有ID我们不允许访问) 谢谢 - 打破了那里的高炮,直截了当! 这篇文章非常有用,因为它帮助我允许 mvc 应用程序中的所有角色,除了某些控制器的“用户”角色。【参考方案2】:

我知道您已经接受了一个答案,这是不久前发布的..(顺便说一句:添加自定义属性的优秀答案),但是我要指出以下几点:

如果你使用过这个属性一次。在单一方法上。这不是一个好的实现。相反,您应该:

[Authorize]   // Just make sure they are auth'ed at all.
public ActionResult EditPosts(int id)

    Post SomePost = findPostByID (id);   // However you do it - single lookup of post

    if (!user.IsInRole("Admin") &&  !IsOwnerOfPost(post) )  Return Not Authorized

  ... Edit post code here

这样做的好处是:

    没有其他人以后会想知道它在哪里使用的其他类。 没有不能在其他任何地方使用的类(您不会通过自定义属性获得重用) 性能更好:单次获取 Post 让人们更容易阅读/弄清楚它是如何工作的。没有可追踪的魔法密码。 多年后,当 HttpContextBase 类不存在,或者用于获取 Id 参数的技巧的其他部分消失时,代码仍然有效...

【讨论】:

以上是关于如何为角色以及特定用户使用自定义授权属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何为特定来电提供自定义振动

使用 .Net Membership / Roles 支持自定义授权/访问规则

如何为 AWS API Gateway 自定义授权方配置 CORS?

如何为 Vuepress 的特定页面使用自定义布局?

如何为特定视图的导航栏设置自定义背景图像

如何为客户特定数据使用通用变量