从 Custom AuthorizeAttribute 获取值是默认的

Getting values from Custom AuthorizeAttribute being default

我有以下自定义 AuthorizeAttribute:

public class SystemAuthorizeAttribute : AuthorizeAttribute
{
   public Form PermissionForm { get; set; } //Enum

   public PermissionValue Permissions { get; set; }//Enum

   public override void OnAuthorization(AuthorizationContext filterContext)
   {                
      //Request is an Authenticated Method?
      if (filterContext.HttpContext.Request.IsAuthenticated)
      {
                Debug.WriteLine("Test 1 " + PermissionForm);
           if (!CurrentUserHasPermissionForm(PermissionForm))
          {
              //Deny access code
          }
      }
   }
  //...
}

登录方法后,它从 HomeController 重定向到索引页面。问题是在我的 HomeController 中使用 SystemAuthorize Attribute 时,Form 值应该为 4(内容)时始终为 0。

HomeController 方法:

[SystemAuthorize(PermissionForm = Form.CONTENT, Permissions = PermissionValue.VIEW)]
public ActionResult Index()
{
    return this.View();
}

登录方式:

[AllowAnonymous]
[Route("Account/Login")]
public ActionResult Login(LoginViewModel model, string url = "")
{
   var user= GetUserAccount(model);
   if (user == null)
   {
     ModelState.AddModelError("", "User not found!");
     return View(model);
   }
   else
   {
       FormsAuthentication.SetAuthCookie(user.Sign, false);

       var authTicket = new FormsAuthenticationTicket(1, user.Sign, DateTime.Now, DateTime.Now.AddMinutes(20), false, JsonConvert.SerializeObject(user));

       var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(authTicket));
                HttpContext.Response.Cookies.Add(authCookie);

                return RedirectToAction("Index", "Home");
    }
}

表单枚举:

 public enum Form : short
    {
        PATIENT = 1,
        USERS = 2,
        MEDICE = 3,
        CONTENT = 4,
    }

我做错了什么或遗漏了什么?

不幸的是,Microsoft 通过在同一个 class 中组合 IAuthorizationFilterAttribute 使这有点混乱。事实上,属性不能除了存储元数据之外的任何事情。

读取 属性的 MVC 部分是 IAuthorizationFilter,当您放置 AuthorizeAttribute(或控制器或操作上的子class)。

但是从属性中实际读取元数据的唯一方法是使用反射。元数据在 class、 中,但与 class 不在同一个实例 中。元数据在 Attribute 中,但过滤器运行时执行的代码在 IAuthorizationFilter 中,它是相同 class.

的单独实例
public class SystemAuthorizeAttribute : AuthorizeAttribute
{
    public Form PermissionForm { get; set; } //Enum

    public PermissionValue Permissions { get; set; }//Enum

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var actionDescriptor = httpContext.Items["ActionDescriptor"] as ActionDescriptor;
        if (actionDescriptor != null)
        {
            var authorizeAttribute = this.GetSystemAuthorizeAttribute(actionDescriptor);

            // If the authorization attribute exists
            if (authorizeAttribute != null)
            {
                // Run the authorization based on the attribute
                var form = authorizeAttribute.PermissionForm;
                var permissions = authorizeAttribute.Permissions;

                // Return true if access is allowed, false if not...
                if (!CurrentUserHasPermissionForm(form))
                {
                    //Deny access code
                }
            }
        }

        return true;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        // Pass the current action descriptor to the AuthorizeCore
        // method on the same thread by using HttpContext.Items
        filterContext.HttpContext.Items["ActionDescriptor"] = filterContext.ActionDescriptor;
        base.OnAuthorization(filterContext);
    }

    private SystemAuthorizeAttribute GetSystemAuthorizeAttribute(ActionDescriptor actionDescriptor)
    {
        SystemAuthorizeAttribute result = null;

        // Check if the attribute exists on the action method
        result = (SystemAuthorizeAttribute)actionDescriptor
            .GetCustomAttributes(attributeType: typeof(SystemAuthorizeAttribute), inherit: true)
            .SingleOrDefault();

        if (result != null)
        {
            return result;
        }

        // Check if the attribute exists on the controller
        result = (SystemAuthorizeAttribute)actionDescriptor
            .ControllerDescriptor
            .GetCustomAttributes(attributeType: typeof(SystemAuthorizeAttribute), inherit: true)
            .SingleOrDefault();

        return result;
    }
}

请注意,OnAuthorization 中有一些逻辑,您需要支持输出缓存和检查 [AllowAnonymous] 的代码部分,因此您不应将授权检查放在那里,但在 AuthorizeCore。但不幸的是,AuthorizeCore 没有通过 ActionDescriptor 你需要检查属性是否存在,所以你需要上面的 httpContext.Items hack 来确保它在同一个线程上传递到那个方法.

如果将 AttributeIAuthorizationFilter 分开成不同的 class,反射部分会变得更加清晰,如 .