自定义授权适用于操作级别,但不适用于控制器级别

时间:2016-01-03 08:45:27

标签: c# asp.net-mvc

据我所知,使用authorize属性修饰的控制器内的所有操作默认采用相同的属性值,(例如,如果控制器授权属性roles = admin,则所有未使用任何属性修饰的操作将自动执行相同的角色=管理员),但这个逻辑在我的情况下不起作用

这里我的自定义授权详情

 public class CustomAuthorize : AuthorizeAttribute
    {
        public string Url { get; set; }
        public string Claims { get; set; }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (!httpContext.User.Identity.IsAuthenticated)
            {
                return false;
            }
            else if (!string.IsNullOrWhiteSpace(Claims))
            {
                var claims = httpContext.GetOwinContext().Authentication.User.HasClaim(t => t.Type == "claim"
                && Claims.Split(',').Contains(t.Value));
                if (!claims)
                {
                    return false;
                }
                else
                    return true;
            }
            else if (!string.IsNullOrWhiteSpace(Roles))
            {
                var roles = httpContext.GetOwinContext().Authentication.User.HasClaim(t => t.Type == "role"
                && Roles.Split(',').Contains(t.Value));
                if (!roles)
                {
                    return false;
                }
                else
                    return true;
            }
            return base.AuthorizeCore(httpContext);
        }

        public bool IsAuthorized(string claim)
        {
            if (!string.IsNullOrEmpty(Claims))
                return Claims.Split(',').Contains(claim);
            return true;
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (!string.IsNullOrEmpty(Url))
                filterContext.Result = new RedirectResult(Url);
            else
                base.HandleUnauthorizedRequest(filterContext);
        }

    }

检查身份验证的辅助方法

 public static bool ActionIsAuthorized(this HtmlHelper helper, string actionName, string controllerName)
        {
            IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
            ControllerBase controller = factory.CreateController(helper.ViewContext.RequestContext, controllerName) as ControllerBase;
            var controllerContext = new ControllerContext(helper.ViewContext.RequestContext, controller);
            var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());
            var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
            AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);
            foreach (var authAttribute in actionDescriptor
                .GetFilterAttributes(true)
                .Where(a => a is CustomAuthorize).Select(a => a as CustomAuthorize))
            {
                authAttribute.OnAuthorization(authContext);
                if (authContext.Result != null)
                    return false;
            }
            return true;
        }

并在视图中用作

@if(Html.ActionIsAuthorized("Index","Appointment", new {area="Employee"})){
    @Html.ActionLink("Appointments","Index","Appointment",new {area = "Employee"})
}

当我使用上面的代码时,它将无效(约会链接仍然显示)

[CustomAuthorize(Claims="Add Appointment",Url="~/Employee/Home/Login")]
public class AppointmentController: BaseController
{
      public ActionResult Index()
      {
          // code here
      }
}

如果我按照以下方式使用它,它可以正常工作

public class AppointmentController: BaseController
{

      [CustomAuthorize(Claims="Add Appointment",Url="~/Employee/Home/Login")]
      public ActionResult Index()
      {
          // code here
      }
}

任何人都可以告诉我为什么当我装饰控制器时,操作默认不采用该属性?或者我错过了什么?

1 个答案:

答案 0 :(得分:2)

看起来问题出在您的自定义ActionIsAuthorized html帮助器中。您只在动作描述符上查找属性,而不是在控制器描述符上查找。因此,请务必查看controllerDescriptor.GetCustomAttributes()

var actionAttributes = actionDescriptor.GetCustomAttributes(typeof(CustomAuthorize), true);
var controllerAttributes = controllerDescriptor.GetCustomAttributes(typeof(CustomAuthorize), true);
var attributes = actionAttributes.Concat(controllerAttributes).OfType<CustomAuthorize>().ToList();
foreach (var authAttribute in attributes)
{
    ...
}