2016-01-03 2 views
0

Как я знаю, все действия внутри контроллера, украшенные атрибутом authorize, будут принимать по умолчанию одно и то же значение атрибута (если контроллер разрешает атрибут 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"}) 
} 

Когда я использую приведенный выше код, как показано ниже, он не будет работать (ссылка назначение еще показано)

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

может кто-нибудь сказать мне, почему действие не принимает атрибут по умолчанию, когда я украшаю контроллер? или я что-то пропустил?

+0

Что вы подразумеваете под «не работает». Вы имеете в виду, что код в CustomAttribute не выполняется по методу «Index», когда вы применяете атрибут на уровне класса? – granadaCoder

+0

@granadaCoder запускается, но не читает значения пользовательских атрибутов (функция ActionIsAuthorized) – mah

ответ

2

Похоже, проблема в вашем обычном ActionIsAuthorized html helper. Вы ищете атрибуты только в дескрипторе действия, а не в дескрипторе контроллера. Поэтому убедитесь, что вы также смотрите в 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) 
{ 
    ... 
} 
+0

, но сработало, но почему действие не наследовало атрибут от контроллера? – mah

+1

Поскольку метод GetCustomAttributes, который вы используете, просто использует Reflection под капюшонами. И Reflection является стандартным артефактом .NET, он абсолютно ничего не знает о контроллерах и действиях ASP.NET MVC и, что более важно, о существовании между ними отношения и правилах наследования для этих атрибутов авторизации. Кстати, вам, вероятно, стоит подумать о том, чтобы использовать некоторое кеширование там, потому что эти рефлексивные призывы к каждому представлению могут испортить производительность вашего приложения. Как вам хорошо известно, отражение происходит медленно. –

Смежные вопросы