2014-11-20 5 views
7

Ich bin neu in .NET, MVC & Identity Framework. Mir ist aufgefallen, dass das Identitäts-Framework es ermöglicht, einzelne Controller-Aktionen über Annotationen zu sichern.Berechtigungsbasierte Autorisierung .net-Identität

[Authorize] 
public ActionResult Edit(int? Id){ 
    //edit action 
} 

Ich möchte bestimmte Aktionen basierend auf Benutzerberechtigungen sichern.

Beispiel: Eine Bloganwendung, in der nur der Benutzer, der einen Blogeintrag erstellt hat, bearbeiten kann.

In diesem Sinne, ist es möglich, beide Optionen unten auszuführen? Wenn ja, gibt es Ressourcen und Beispiele dafür, wie Sie am besten erreichen können?

[Authorize(Entity = "Entry", Permission = "Edit", Id = Id)] 
public ActionResult Edit(int? Id){ 
    //edit action 
} 

oder

[BlogEntryPermission(Permission = "Edit", Id = Id)] 
public ActionResult Edit(int? Id){ 
    //edit action 
} 

Wo Blog Id aus der Anforderung erfasst wird.

Jede Information oder Richtung auf Berechtigung basierte Authentifizierung würde am meisten geschätzt werden. Vielen Dank im Voraus für Ihre Hilfe.

Antwort

6

Sie können Ihre benutzerdefinierten implementieren AuthorizationAttribute, wo Sie Ihre Parameter angeben wird und eine blogId aus Anfrage

es wie
public class AuthorizeEntryPermission : AuthorizeAttribute 
{ 
     public string Permission { get; set; } 

     public AuthorizeEntryPermission(){ 
     } 

     public AuthorizeEntryPermission(string Permission) 
     { 
      this.Permission = Permission; 
     } 

     protected override bool AuthorizeCore(HttpContextBase httpContext) 
     { 
      var id = context.Request.RequestContext.RouteData.Values["Id"]; 
      //check your permissions 
     } 

     public override void OnAuthorization(AuthorizationContext filterContext) 
     { 
      if (AuthorizeCore(filterContext.HttpContext)) 
      { 
       // ** IMPORTANT ** 
       // Since we're performing authorization at the action level, the authorization code runs 
       // after the output caching module. In the worst case this could allow an authorized user 
       // to cause the page to be cached, then an unauthorized user would later be served the 
       // cached page. We work around this by telling proxies not to cache the sensitive page, 
       // then we hook our custom authorization code into the caching mechanism so that we have 
       // the final say on whether a page should be served from the cache. 

       HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache; 
       cachePolicy.SetProxyMaxAge(new TimeSpan(0)); 
       cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */); 
      } 
      else 
      { 
       //handle no permission 
      } 
     } 

     private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) 
     { 
      validationStatus = OnCacheAuthorization(new HttpContextWrapper(context)); 
     } 
    } 

Dann nutzen Sie dieses nicht erhalten:

[AuthorizeEntryPermission(Permission = "Edit")] 
public ActionResult Edit(int? Id){ 
    //edit action 
} 
+0

Vielen Dank für die Richtung.Beim Versuch, auf die Pfadvariable zuzugreifen, tritt jetzt ein Problem auf. var id = httpContext.Request.Form ["BlogId"]; funktioniert nicht für Pfadparameter, die wie folgt definiert sind:/BlogPost/Edit/1. Gibt es eine saubere Möglichkeit, auf diese Variable zuzugreifen? context.Request.RequestContext.RouteData.Values.ElementAt (2) .Wert funktioniert, aber nicht sicher ist etwas, auf das ich mich verlassen möchte. – mcroteau

+1

@croteau Sie können 'context.Request.RequestContext.RouteData.Values ​​[" Id "]' –

1

MVC hat Rollen eingebaut. Sie können die Rollen so granular gestalten, wie Sie benötigen - im Wesentlichen wie Berechtigungen.

  • EditBlogPost
  • AddBlogPost
  • ViewBlogPost

Dann können Sie die Rollen einrichten auf dem Controller des eingebauten in AuthorizeAttribute mit: Zum Beispiel könnten Sie Rollennamen wie machen.

Dann ist es nur eine Frage der Zuordnung der verschiedenen Rollen zu jedem Benutzer in Ihrer Datenbank.

+2

verwenden Sie müssen jedoch vorsichtig mit diesem Ansatz sein. Es gibt eine maximale Größe für das Cookie-Limit. In einer großen Anwendung können Sie Tausende von granularen Rollen haben – Shoe

+0

Guter Punkt. Das OP sagte jedoch, er wollte Berechtigungen für einen Blog - was bedeutet, dass es nicht so viele Controller zu verwalten gibt. Aber wenn es eine große Anzahl von Berechtigungen gibt, stimme ich zu, dass das Anpassen des AuthorizeAttribute ein besserer Weg ist. – NightOwl888

+0

@Shoe - Eigentlich müssen Sie die Rollen nicht unbedingt im Cookie speichern. Sie können es einfach einrichten, um sie pro Anfrage zu laden oder sie pro Benutzer zwischenzuspeichern. Oder Sie können die Rollen mit bitweisen IDs einrichten, sodass Sie nur eine einzige lange Zahl im Cookie speichern müssen. – NightOwl888

1

Ich hoffe, dass Ihr Problem bis jetzt gelöst wurde. Aber es lohnt sich, eine neue Lösung hinzuzufügen. Ich habe eine Permission-basierte Erweiterung für Microsoft Identity 2-Mitgliedschaft-System implementiert. Es ist ein Open-Source-Projekt und Sie können hier auf das Repository zugreifen:

https://github.com/Arminkhodaei/Identity-Permission-Extension

Verbrauch:

Erster Ansatz:

// GET: /Manage/Index 
[AuthorizePermission(Name = "Show_Management", Description = "Show the Management Page.")] 
public async Task<ActionResult> Index(ManageMessageId? message) 
{ 
    //... 
} 

Zweiter Ansatz:

// GET: /Manage/Users 
public async Task<ActionResult> Users() 
{ 
    if (await HttpContext.AuthorizePermission(name: "AllUsers_Management", description: "Edit all of the users information.")) 
    { 
     return View(db.GetAllUsers()); 
    } 
    else if (await HttpContext.AuthorizePermission(name: "UnConfirmedUsers_Management", description: "Edit unconfirmed users information.")) 
    { 
     return View(db.GetUnConfirmedUsers()); 
    } 
    else 
    { 
     return View(new List<User>()); 
    } 
} 
+0

Hi Armin, kann ich dieses AuthorizePermission-Attribut auf Controller-Ebene verwenden? – Alienalone

+0

Hallo, @ Alienalone, Sicher kannst du. Um weitere Anweisungen und Erläuterungen zu erhalten, können Sie den Abschnitt ** Verwendung ** der Dokumentation lesen. –

+0

Danke. Ich habe es versucht und es funktioniert perfekt für mich. Danke nochmal – Alienalone