Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 授权具有多个角色的属性_C#_Asp.net Mvc_Authorization - Fatal编程技术网

C# 授权具有多个角色的属性

C# 授权具有多个角色的属性,c#,asp.net-mvc,authorization,C#,Asp.net Mvc,Authorization,我想为一个控制器同时添加多个角色的授权 通常情况下,情况如下所示: [Authorize(Roles = "RoleA,RoleB,RoleC")] public async Task<ActionResult> Index() { } 我不能这样做,因为字符串必须在编译时已知: [Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)] public async Task<ActionResult> Index() {

我想为一个控制器同时添加多个角色的授权

通常情况下,情况如下所示:

[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}
我不能这样做,因为字符串必须在编译时已知:

[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}
[授权(角色=string.join(“,”,RoleA,RoleB,RoleC)]
公共异步任务索引()
{
}
有没有办法绕过这个问题

我可以写一个只包含“RoleA,RoleB,RoleC”的常量,但我不喜欢魔法字符串,这是一个魔法字符串。更改角色名称并忘记更改组合字符串将是一场灾难


我使用的是MVC5.ASP.NET标识,角色在编译时已知。

尝试创建自定义授权属性,如

假设多个控制器的角色相同,请创建帮助器类:

public static class Role
{
    public const string Administrator = "Administrator";
    public const string Assistant = "Assistant";
}
然后像这样使用它:

public class MyController : Controller
{
    [AuthorizeRoles(Role.Administrator, Role.Assistant)]
    public ActionResult AdminOrAssistant()
    {                       
        return View();
    }
}

确保您是从
System.Web.Mvc.AuthorizeAttribute
派生自定义属性类,而不是
System.Web.Http.AuthorizeAttribute

我遇到了同样的问题。一旦我改变了它,一切都正常了

您可能还希望将以下内容添加到自定义属性类中:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 

我发现解决这个问题的最好和最简单的方法就是在Authorize属性中连接角色

[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]
对于CustomRole,类具有如下常量字符串:

public static class CustomRoles
{
    public const string Admin = "Admin";
    // and so on..
}

我觉得自定义授权属性对于这个问题来说太过了,除非你有大量的角色

由于字符串必须在编译时已知,为什么不创建一个静态角色类,该类包含已定义角色的公共字符串,然后添加逗号分隔的字符串和要授权的特定角色:

public static class Roles
{
    public const string ADMIN = "Admin";
    public const string VIEWER = "Viewer";

    public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER;
}
然后,您可以在控制器类或控制器方法(或两者)上使用类似的Authorize属性:


我所做的就是@Tieson中的答案

我在他的答案中做了一些调整。而不是字符串。为什么不把它转换成列表呢

以下是我的答案:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    private new List<string> Roles;
    public AuthorizeRolesAttribute(params string[] roles) : base()
    {
        Roles = roles.toList()
    }
}

现在,它正在验证角色是否有权访问资源

您使用的是public const string RoleA=“RoleA”;还是如您所述?可能与now重复这是一个值得Mac Gyver的想法;)我也非常喜欢这个解决方案,特别是因为我可以让我的角色是枚举而不是字符串。在项目层次结构中,放置此自定义授权属性的好名称空间和位置是什么?@SimonShine-我认为,您应该将其放置在web项目中,例如属性文件夹中。但是,如果您在一个解决方案中有多个项目,您需要将其移动到每个项目可见的另一个库中。我不确定这里发生了什么,但这对我没有帮助,任何用户,无论角色如何,都可以访问该方法。与@Urielzen相同的问题,但Jerry Finegan(使用“System.Web.Mvc.AuthorizeAttribute而非System.Web.Http.AuthorizeAttribute”)可值;但这应该是注释;不是答案。如果正确实现,您的答案和接受的答案都将触发授权(我在生产Web应用程序中使用接受的)。建议进行编辑以删除有关已接受答案的注释。如果角色是枚举,则可以使用类似于[授权(角色=nameof(UserRoleEnum.User)+”,“nameof(UserRoleEnum.Admin))]此示例不起作用,或者至少不是您可能认为的方式。例如,尽管操作上的
ADMIN\u或\u VIEWER
角色是多余的,因为如果您还没有
ADMIN
角色,您将无法访问
Create
方法。在这种情况下,
VIEWER
将永远无法调用
Create
方法。此解决方案也不可扩展。在某一点上,您有太多具有不同操作的角色,不应该创建每个组合。我刚刚尝试了此方法,发现引用了库
System.Web.Http.AuthorizeAttribute
,而不是
System.Web.Mvc.AuthorizeAttribute
public static class Roles
{
    public const string ADMIN = "Admin";
    public const string VIEWER = "Viewer";

    public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER;
}
[Authorize(Roles = Roles.ADMIN]
public class ExampleController : Controller
{
    [Authorize(Roles = Roles.ADMIN_OR_VIEWER)
    public ActionResult Create()
    {
        ..code here...
    }
}
public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    private new List<string> Roles;
    public AuthorizeRolesAttribute(params string[] roles) : base()
    {
        Roles = roles.toList()
    }
}
public override void OnAuthorization(HttpActionContext actionContext)
{
            if (Roles == null)
                HandleUnauthorizedRequest(actionContext);
            else
            {
                ClaimsIdentity claimsIdentity = HttpContext.Current.User.Identity as ClaimsIdentity;
                string _role = claimsIdentity.FindFirst(ClaimTypes.Role).Value;
                bool isAuthorize = Roles.Any(role => role == _role);

                if(!isAuthorize)
                    HandleUnauthorizedRequest(actionContext);
            }
        }