3

使用 [Authorize] 属性很容易将操作设置为仅由特定用户或角色允许。例如

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

但是,当我想要反转时遇到了问题。有没有办法使用 MVC 框架功能来允许所有经过身份验证的用户,除了那些由名称或角色指定的用户?

所需的用法类似于:

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

5 回答 5

6

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

/// <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>();
    }
}
于 2012-12-14T00:16:39.867 回答
1

您可以只列出接受的角色并将异常排除在外

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

或者使用该逻辑创建一个特殊的 AuthorizeAttribute

于 2012-12-14T00:21:45.317 回答
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"

于 2020-08-04T13:07:39.257 回答
1

以下代码简单地否定授予指定用户/角色的授权,有效地成为除指定用户/角色之外的所有人的授权。

就像使用 AuthorizeAttribute 类一样使用它。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class DoNotAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext) => !base.AuthorizeCore(httpContext);
}
于 2020-12-24T11:55:25.223 回答
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
}
于 2020-07-20T07:40:47.887 回答