Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自定义授权在操作级别工作,但不在控制器级别工作_C#_Asp.net Mvc - Fatal编程技术网

C# 自定义授权在操作级别工作,但不在控制器级别工作

C# 自定义授权在操作级别工作,但不在控制器级别工作,c#,asp.net-mvc,C#,Asp.net Mvc,正如我所知,默认情况下,控制器内所有使用authorize属性修饰的操作都将采用相同的属性值(例如,如果控制器authorize属性roles=admin,则所有未使用任何属性修饰的操作都将自动采用相同的role=admin),但这种逻辑在我的情况下不起作用 这是我的客户授权详情 public class CustomAuthorize : AuthorizeAttribute { public string Url { get; set; } publ

正如我所知,默认情况下,控制器内所有使用authorize属性修饰的操作都将采用相同的属性值(例如,如果控制器authorize属性roles=admin,则所有未使用任何属性修饰的操作都将自动采用相同的role=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"})
}
当我按如下方式使用上述代码时,它将不起作用(仍显示约会链接)

如果我用下面的方法使用它,它会工作

public class AppointmentController: BaseController
{

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

有谁能告诉我,当我用装饰控制器时,为什么默认情况下操作不采用该属性?或者我错过了什么?

看起来问题出在您的自定义
操作已授权的
html帮助程序中。您只在操作描述符上查找属性,而不在控制器描述符上查找属性。因此,请确保同时查看
controllerDescriptor.GetCustomAttributes()

var actionAttributes=actionDescriptor.GetCustomAttributes(typeof(CustomAuthorize),true);
var controllerAttributes=controllerDescriptor.GetCustomAttributes(typeof(CustomAuthorize),true);
var attributes=actionAttributes.Concat(controllerAttributes).OfType().ToList();
foreach(属性中的var authtribute)
{
...
}

你所说的“不起作用”是什么意思。您的意思是当您在类级别应用属性时,CustomAttribute中的代码不会在“Index”方法上执行吗?@granadaCoder它会运行,但不会读取自定义属性值(函数ActionIsAuthorized)它起作用了,但是为什么操作没有从控制器继承属性呢?因为您正在使用的
GetCustomAttributes
方法只是在引擎盖下使用反射。反射是一个标准的.NET工件,它完全不知道ASP.NET MVC控制器和操作,更重要的是,它不知道它们之间存在的关系以及这些授权属性的继承规则。顺便说一下,您可能应该考虑在那里使用一些缓存,因为每个视图上的反射调用可能会破坏应用程序的性能。正如你所知道的,反射是缓慢的。
public class AppointmentController: BaseController
{

      [CustomAuthorize(Claims="Add Appointment",Url="~/Employee/Home/Login")]
      public ActionResult Index()
      {
          // code here
      }
}
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)
{
    ...
}