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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11493873/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 18:03:52  来源:igfitidea点击:

How to use custom Authorize attribute for roles as well as a specific user?

c#asp.net.netasp.net-mvc-3

提问by Freeman

so i have my Action Method

所以我有我的行动方法

[Authorize(Roles="Admin")]
public ActionResult EditPosts(int id)
{
    return View();
}

In my case i need to authorize administrators so they can edit posts but (here comes the cool part), i also need to allow the creator of the post to be able to edit the post wich is a normal user. So how can i filter out the user that created the post as well as the admins but leave the others unauthorized? I am recieveing the PostEntry id as a route parameter but thats after the atribute and also attributes only accept constant parameters, looks like something very difficult, your answers are highly appreciated, Cheers!

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

采纳答案by Darin Dimitrov

You could write a custom authorize attribute:

您可以编写自定义授权属性:

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();
    }
}

and then decorate your controller action with it:

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

[AuthorizeAdminOrOwnerOfPost]
public ActionResult EditPosts(int id)
{
    return View();
}

回答by Traderhut Games

I understand that you have already accepted an answer, and this was posted a while back.. (btw:excellent answer for adding custom attributes), However I would point out the following:

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

If you are using this attribute once. On a Single method. This isn't a good implementation. Instead you should have:

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

[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
}

This has the advantages of:

这具有以下优点:

  1. No additional class that someone will later wonder where it is used.
  2. No class that isn't usable anywhere else (you don't gain reuse with a custom attribute)
  3. Performance is better: Single fetch of the Post
  4. Way easier for someone to read/figure out how it works. No magic code to track down.
  5. And Years later, when HttpContextBase class doesn't exist, or other parts of the tricks used to fetch the Id parameter are gone, the code still works...
  1. 没有其他人以后会想知道它在哪里使用的附加类。
  2. 没有在其他任何地方都无法使用的类(您不会通过自定义属性获得重用)
  3. 性能更好:Post 的单次获取
  4. 有人更容易阅读/弄清楚它是如何工作的。没有神奇的代码可以追踪。
  5. 多年后,当 HttpContextBase 类不存在,或者用于获取 Id 参数的其他部分技巧消失时,代码仍然有效......