一个动作可以授权除给定用户/角色之外的所有人吗?

时间:2012-12-14 00:16:40

标签: c# asp.net-mvc

使用[Authorize]属性可以轻松设置仅允许特定用户或角色执行的操作。例如。

[Authorize(Roles = "Administrator")]
public ActionResult Index()
{
  ...

然而,当我想要逆时,我遇到了一个问题。有没有办法使用MVC框架功能允许所有经过身份验证的用户除了由名称或角色指定的用户?

所需的用法类似于:

[DoNotAuthorize(Roles = "RestrictedUser")]
public ActionResult Index()
{
  ...

4 个答案:

答案 0 :(得分:5)

一个相当简单的解决方案是从AuthorizeAttribute类派生并覆盖其AuthorizeCore方法,交换其true / false逻辑。

/// <summary>
/// Authorizes any authenticated user *except* those who match the provided Users or Roles.
/// </summary>
public class DoNotAuthorizeAttribute : AuthorizeAttribute
{
    /// <summary>
    /// This is effectively a copy of the MVC source for AuthorizeCore with true/false logic swapped.
    /// </summary>
    /// <param name="httpContext">The HTTP context, which encapsulates all HTTP-specific information about an individual HTTP request.</param>
    /// <returns>true if the user is authorized; otherwise, false.</returns>
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException("httpContext");
        }
        IPrincipal user = httpContext.User;
        if (!user.Identity.IsAuthenticated)
        {
            return false;
        }

        string[] usersSplit = SplitString(Users);
        if ((usersSplit.Length > 0) && usersSplit.Contains<string>(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
        {
            return false;
        }

        string[] rolesSplit = SplitString(Roles);
        if ((rolesSplit.Length > 0) && rolesSplit.Any<string>(new Func<string, bool>(user.IsInRole)))
        {
            return false;
        }

        return true;
    }

    /// <summary>
    /// This is a direct copy of the MVC source for the internal SplitString method.
    /// </summary>
    /// <param name="original">The original string to split.</param>
    /// <returns>An array of strings.</returns>
    internal static string[] SplitString(string original)
    {
        if (string.IsNullOrWhiteSpace(original))
        {
            return new string[0];
        }
        return (from piece in original.Split(new[] { ',' })
                let trimmed = piece.Trim()
                where !string.IsNullOrEmpty(trimmed)
                select trimmed).ToArray<string>();
    }
}

答案 1 :(得分:2)

您可以列出已接受的角色并将异常退出

[Authorize(Roles = "Administrator, Admin, SuperUser")]
public ActionResult Index()
{
}

或者使用该逻辑

创建一个特殊的AuthorizeAttribute

答案 2 :(得分:1)

旧问题,但是对于那些需要它的人-非常简单,您可以使用Policy来处理它:

只需添加类:

public class CustomRoleRequirement : AuthorizationHandler<CustomRoleRequirement>, IAuthorizationRequirement
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRoleRequirement requirement)
    {
        var roles = new[] { "YourExcludedRole1", "YourExcludedRole2", "YourExcludedRole3"}; 
        var userIsInRole = roles.Any(role => context.User.IsInRole(role));
        if (userIsInRole)
        {
            context.Fail();
            return Task.FromResult(false);
        }

        context.Succeed(requirement);
        return Task.FromResult(true);
    }
}

然后将其添加到startup.cs

public void ConfigureServices(IServiceCollection services)
{
     ...

     services.AddAuthorization(options => {
            options.AddPolicy("ExcludeRoles", policy => policy.AddRequirements(new CustomRoleRequirement()));
        });

     ...
}

然后您只需使用[Authorize(Policy = "ExcludeRoles")],所有角色将被授权排除在"YourExcludedRole1", "YourExcludedRole2", "YourExcludedRole3"

答案 3 :(得分:0)

伙计。这是授权特定用户并将其分配给不同控制器或操作的最简单方法。创建一个简单的静态类并创建const变量。

public static class RolesText
    {
        public const string MISDeveloper = "MIS Developer";
        public const string SuperAdmin = "Super Admin";
        public const string Admin = "Admin";
        public const string DistrictMnE = "District M&E";
        public const string PSUEngineer = "PSU Engineer";
        public const string Guest = "Guest";

        public const string All_Users = MISDeveloper + "," + SuperAdmin + "," + Admin + "," + DistrictMnE + "," + PSUEngineer + "," + Guest;
        public const string Without_PSUEng_DistMnE = MISDeveloper + "," + SuperAdmin + "," + Admin + "," + Guest;
        public const string Without_PSUEng_Guest = MISDeveloper + "," + SuperAdmin + "," + Admin + "," + DistrictMnE;
        public const string Without_DistMnE_Guest = MISDeveloper + "," + SuperAdmin + "," + Admin + "," + PSUEngineer;
    }

然后按如下所示调用这些值。

[Authorize(Roles = RolesText.Without_PSUEng_Guest)]
    public class NeedBasedSMsController : Controller
    {
        private AUPDBEntities db = new AUPDBEntities();
    }

或如果要分配其他用户。然后按以下方式命名。

[Authorize(Roles = RolesText.Admin + "," + RolesText.Guest)]
public class MyController : Controller
{
    // YOUR CONTROLLER CLASS
}

享受!!!