从Custom AuthorizeAttribute获取值是默认值

时间:2017-10-05 14:12:07

标签: c# authorize-attribute

我有以下Custom 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
          }
      }
   }
  //...
}

在Login方法之后,它从HomeController重定向到Index页面。问题是当我的HomeController中使用SystemAuthorize属性时,Form值始终为0时应为4(内容)。

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,
    }

我做错了什么或错过了什么?

1 个答案:

答案 0 :(得分:2)

不幸的是,微软通过在同一个课程中将IAuthorizationFilterAttribute相结合,使这一点变得有些混乱。事实上,除了商店元数据之外,属性不能

读取属性的MVC部分是IAuthorizationFilter,当你将AuthorizeAttribute(或子类)放在一个MVC上时,它会自动向MVC注册。控制者或行动。

但实际从属性中读取元数据的唯一方法是使用Reflection。元数据位于同一类中,但不是该类的实例。元数据位于Attribute中,但过滤器运行时执行的代码位于IAuthorizationFilter,这是同一类的单独实例。

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中的DT[a==3, c := DT2[DT[a==3], c, on = c(b="b")]] DT # a b c #1: 1 1 NA #2: 2 2 NA #3: 3 3 10 #4: 1 4 NA #5: 2 5 NA #6: 3 6 10 #7: 1 7 NA #8: 2 8 NA #9: 3 9 10 分开,与this example中的shell script分开,则反映部分会变得更加清晰。