0

J'ai des contrôleurs avec des actions, qui fonctionnent avec certaines entités (Driver). En outre, chaque pilote est lié avec le profil d'identité.Comment implémenter du code dans de nombreuses actions de plusieurs contrôleurs

 public async Task<ActionResult> Details(int? id) 
     { 
      if ((id == null)) 
      { 
       return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
      } 
      DriverDetailVM model = mapper.Map<DriverDetailVM>(db.Drivers.Find(id)); 
      if ((model == null)) 
      { 
       return HttpNotFound(); 
      } 
      return View(model); 
     } 

     public async Task<ActionResult> Edit(int? id = null, bool isNewUser = false) 
     { 
///////// 
     } 

Si l'utilisateur a le rôle "Superadmin", il a accès aux pages avec n'importe quelle valeur d'identifiant. Si l'utilisateur a un rôle "Pilote" alors nous ne devrions avoir accès que si la valeur de l'identifiant est la même que celle de son profil. J'essaie de mettre en œuvre sur ActionFilter:

public class DriverAccessActionFilterAttribute : ActionFilterAttribute 
{ 
    public string IdParamName { get; set; } 
    public int DriverID { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (filterContext.HttpContext.User.IsInRole("Driver")) 
     { 
      if (filterContext.ActionParameters.ContainsKey(IdParamName)) 
      { 
       var id = filterContext.ActionParameters[IdParamName] as Int32; 
       if (id != DriverID) 
        filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden); 
      } 
      else 
       filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
     } 
     else 
      base.OnActionExecuting(filterContext); 
    } 
} 

mais quand je tente d'utiliser ce code:

[DriverAccessActionFilter(DriverID = currentUser.DriverId, IdParamName = "id")] 
    public async Task<ActionResult> Details(int? id) 
    { 

il ne veut pas être compilé, car

Une référence d'objet est requis pour le champ non statique, la méthode ou la propriété

comment l'implémenter?

Répondre

2

Les paramètres d'attribut sont évalués au moment de la compilation, pas au moment de l'exécution. Donc, ils doivent être des constantes de temps de compilation. Vous ne pouvez pas transmettre de valeur à un attribut d'action au moment de l'exécution. Par exemple, au [DriverAccessActionFilter(DriverID = currentUser.DriverId, IdParamName = "id")], vous passez le DriverID = currentUser.DriverId. Un attribut est utilisé comme métadonnées de contrôleur/action et les métadonnées doivent être compilées dans l'assemblage. C'est pourquoi les attributs ne peuvent prendre que des valeurs constantes.

Vous devez changer votre attribut comme suit:

  1. Utiliser l'injection de dépendances à Injecter votre service qui retourne utilisateur connecté.
  2. Ou Implémentez un Principal personnalisé et affectez-lui le principal de la demande en cours.

Vous pouvez modifier votre attribut comme suivre au cas où vous mettre en œuvre CustomPrinicpal:

public class DriverAccessActionFilterAttribute : ActionFilterAttribute 
    { 
     public string IdParamName { get; set; } 
     private int DriverID { get; set; } 

     public override void OnActionExecuting(ActionExecutingContext filterContext) 
     {    
      if (filterContext.HttpContext.User.IsInRole("Driver")) 
      { 
       var customPrincipal = filterContext.HttpContext.User as CustomPrincipal; 
       DriverID = customPrincipal.Id; 
       // Rest of you logic     
      } 
      else 
       base.OnActionExecuting(filterContext); 
     } 
    } 

Si vous choisissez chemin de DI, vous pouvez utiliser l'extrait suivant:

public class DriverAccessActionFilterAttribute : ActionFilterAttribute 
{ 
    public string IdParamName { get; set; } 
    private int DriverID { get; set; } 

    public DriverAccessActionFilterAttribute(IYourIdentityProvider provider) 
    { 
     DriverID = provider.LoggedInUserID; 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    {    
     // Your logic 
    } 
} 

puis utilisez votre attribut comme [DriverAccessActionFilter(IdParamName = "id")]

+0

J'ai pensé au principal, merci –

+0

Vous êtes les bienvenus et essayons de conduire de 'AuthorizationFilterAttribute' au lieu de' ActionFilterAttribute'. – Zeeshan