如何扩展 AuthorizeAttribute 并检查用户的角色

发布于 2024-10-19 03:16:46 字数 1114 浏览 2 评论 0原文

我正忙着为名为 MyAuthorizeAttribute 的操作方法编写自己的自定义属性,我仍在忙于编写代码,这是我的部分代码:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class  MyAuthorizeAttribute : AuthorizeAttribute
{
   public new Role Roles;

   public override void OnAuthorization(AuthorizationContext filterContext)
   {
      base.OnAuthorization(filterContext);

      if (Roles != 0)  // Did it this way to see what the value of Roles was
         return;

      // Here I am going to get a list of user roles
      // I'm doing my own database calls

      filterContext.Result = new HttpUnauthorizedResult();
   }
}

这是我的角色枚举:

public enum Role
{
   Administrator = 1,
   SuperAdministrator = 2
}

我的操作方法:

[MyAuthorize(Roles = Role.Administrator|Role.SuperAdministrator)]
public ActionResult Create()
{
   return View();
}

我没有使用 Roles = "Administrator 的原因,超级管理员”是因为角色是硬编码的。如果角色名称发生变化,我不想有 100 个地方需要更改。

根据我的方法,当到达 if (Roles != 0) then Roles 总值为 3 时,我如何检查这 2 个角色是否在特定用户的用户角色列表中?

我在这里做得正确吗?如果不是,我将如何实施这个?它不一定是我做的方式。

I am busy writing my own custom attribute for my action method called MyAuthorizeAttribute, I am still busy writing the code, here is my partial code:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class  MyAuthorizeAttribute : AuthorizeAttribute
{
   public new Role Roles;

   public override void OnAuthorization(AuthorizationContext filterContext)
   {
      base.OnAuthorization(filterContext);

      if (Roles != 0)  // Did it this way to see what the value of Roles was
         return;

      // Here I am going to get a list of user roles
      // I'm doing my own database calls

      filterContext.Result = new HttpUnauthorizedResult();
   }
}

Here is my Role enum:

public enum Role
{
   Administrator = 1,
   SuperAdministrator = 2
}

My action method:

[MyAuthorize(Roles = Role.Administrator|Role.SuperAdministrator)]
public ActionResult Create()
{
   return View();
}

The reason why I did not use Roles = "Administrator,SuperAdministrator" was because the roles are hard-coded. I don't want to have a 100 places to change if the role name changes.

Given my method, when it gets to if (Roles != 0) then Roles total value is 3, how would I check to see if these 2 roles is in the list of user roles for a specific user?

Am I doing it correct here? If not how would I otherwise implement this? It doesn't have to be the way that I did it in.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

病女 2024-10-26 03:16:46

如果 MyAuthorizeAttribute 接受 IList (或类似的)不是更好吗
这样它既是类型安全的,但您不必使用位标志。
如果您想保存结果,位标志非常有用,但这是另一种方式。

编辑(现在带有示例):

Attribute:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public Role[] RoleList { get; set; }


    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException("httpContext");
        }
        IPrincipal user = httpContext.User;
        if (!user.Identity.IsAuthenticated)
        {
            return false;
        }
        //Only role access is implemented here
        /*if ((this._usersSplit.Length > 0) && !this._usersSplit.Contains<string>(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
        {
            return false;
        }*/
        if ((RoleList.Length > 0) && !RoleList.Select(p=>p.ToString()).Any<string>(new Func<string, bool>(user.IsInRole)))
        {
            return false;
        }
        return true;
    }

}

控制器:

[MyAuthorize(RoleList = new []{Role.Administrator , Role.SuperAdministrator} )]
    public ActionResult Create()
    {
        return View();
    }

Would it not be better if MyAuthorizeAttribute accepted an IList ( or similar)
That way it is both typesafe, but you don't have to use bit flags.
Bit flags are great if you want to save the reult, but this is the other way.

Edit (Now with examples):

Attribute:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public Role[] RoleList { get; set; }


    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException("httpContext");
        }
        IPrincipal user = httpContext.User;
        if (!user.Identity.IsAuthenticated)
        {
            return false;
        }
        //Only role access is implemented here
        /*if ((this._usersSplit.Length > 0) && !this._usersSplit.Contains<string>(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
        {
            return false;
        }*/
        if ((RoleList.Length > 0) && !RoleList.Select(p=>p.ToString()).Any<string>(new Func<string, bool>(user.IsInRole)))
        {
            return false;
        }
        return true;
    }

}

Controller:

[MyAuthorize(RoleList = new []{Role.Administrator , Role.SuperAdministrator} )]
    public ActionResult Create()
    {
        return View();
    }
生死何惧 2024-10-26 03:16:46

如果我理解正确,这里的问题不在于继承 AuthorizeAttribute,而是比较枚举值。您可能需要一个可以用作位标志的枚举类型 - 如果是这样,请查看 C# 编程指南中有关枚举类型的部分,尤其是第二部分“作为位标志的枚举类型”。

澄清一下:

您现在可以执行以下操作,而不只是检查 Roles!=0

public override void OnAuthorization(AuthorizationContext filterContext)
{
    base.OnAuthorization(filterContext);

    // Here you get an enum indicating the roles this user is in. The method
    // converts the db information to a Role enum before it is returned.
    // If the user is not authenticated, the flag should not be set, i.e. equal 0.
    Role userRole = GetUserRolesFromDatabase();

    // Bitwise comparison of the two role collections.
    if (Roles & userRole > 0)
    {
        // The user is in at least one of the roles in Roles. Return normally.
        return;
    }

    // If we haven't returned yet, the user doesn't have the required privileges.
    new HttpUnauthorizedResult(); 
}

为了使比较更容易,您可以在枚举上使用以下扩展方法:

public static class RolesExtensions
{
    public static bool HasAnyOf(this Roles r1, Roles roles)
    {
        return (r1 & roles) > 0;
    }
}

If I understand correctly, your problem here is not with inheriting the AuthorizeAttribute, but rather with comparing enum values. You probably want an enum type that you can use as a bit flag - if so, take a look at the section about Enumeration Types in the C# Programming guide especially the second part, "Enumeration Types as Bit Flags".

To clarify a bit:

Instead of just checking Roles!=0, you could now do something like this:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    base.OnAuthorization(filterContext);

    // Here you get an enum indicating the roles this user is in. The method
    // converts the db information to a Role enum before it is returned.
    // If the user is not authenticated, the flag should not be set, i.e. equal 0.
    Role userRole = GetUserRolesFromDatabase();

    // Bitwise comparison of the two role collections.
    if (Roles & userRole > 0)
    {
        // The user is in at least one of the roles in Roles. Return normally.
        return;
    }

    // If we haven't returned yet, the user doesn't have the required privileges.
    new HttpUnauthorizedResult(); 
}

To make the comparison easier, you could use the following extension method on your enum:

public static class RolesExtensions
{
    public static bool HasAnyOf(this Roles r1, Roles roles)
    {
        return (r1 & roles) > 0;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文