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

hem*_*emp 3 c# asp.net-mvc

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

[Authorize(Roles = "Administrator")]
public ActionResult Index()
{
  ...
Run Code Online (Sandbox Code Playgroud)

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

期望的用法类似于:

[DoNotAuthorize(Roles = "RestrictedUser")]
public ActionResult Index()
{
  ...
Run Code Online (Sandbox Code Playgroud)

hem*_*emp 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>();
    }
}
Run Code Online (Sandbox Code Playgroud)