2009-04-24 11 views
4

Ich untersuche derzeit alternative Lösungen für die Standard-Seite Autorisierung Konfiguration in asp.net.ASP.NET Seite Autorisierung ... Wie machst du es?

Das Standort-Tag funktioniert, wenn Sie Verzeichnisse von Dateien haben, die die gleiche Zugriffsrichtlinie benötigen, aber wenn Sie viele individuelle Zugriffsrichtlinien haben, ist das Standort-Tag ein Problem. Ich könnte mein eigenes benutzerdefiniertes Auth-System rollen, aber wenn es vermieden werden kann, ist das wahrscheinlich besser.

Derzeit verwenden wir ein Azman-ähnliches, auf Berechtigungen basierendes Autorisierungssystem für den Seiteninhalt, aber ich habe noch keine gute Möglichkeit gefunden, dies mit der Standardseiten-Sicherheit zu integrieren.

Irgendwelche Vorschläge, wie man das macht? Gibt es Lösungen, die die Seitenberechtigung von azman und asp.net integrieren? Gibt es andere Standardlösungen, auf die ich achten sollte?

Antwort

6

habe ich in einer großen Anwendung viele unterschiedliche Berechtigungen und verschiedene Rollen in etwa wie folgt mit [ich den Code nicht hier haben, so werde ich nur versuchen, es neu zu erstellen hier]:

ich zum ersten Mal umgesetzt eine Klasse namens SecuredPage, wie folgend:


public class SecuredPage : System.Web.UI.Page 
{ 
    // Those Permissions are mandatory, so user needs to have all of them 
    public List MandatoryPermissions { get; set; } 

    // Those Permissions are optional, so if the user have at least one of them, he can access 
    public List OptionalPermissions { get; set; } 

    protected override void OnLoad(EventArgs e) 
    { 
     MyUser loggedUser = (MyUser) this.User; 

     base.OnLoad(e); 

     foreach (Permission mandatoryPermission in MandatoryPermissions) 
     { 
      // if the user don't have permission, we can redirect him 
      if (!loggedUser.HasPermission(mandatoryPermission)) 
      { 
       RedirectToDontHaveAccess(); 
       break; 
      } 
     } 

     bool hasAccessToThePage = false; 

     foreach (Permission optionalPermission in OptionalPermissions) 
     { 
      // If the user has at least one of the permissions, he can access 
      if (loggedUser.HasPermission(optionalPermission)) 
      { 
       hasAccessToThePage = true; 
      } 
     } 

     if (!hasAccessToThePage) 
     { 
      RedirectToDontHaveAccess(); 
     } 

    } 

    private void RedirectToDontHaveAccess() 
    { 
     throw new NotImplementedException(); 
    } 
} 

Dies wird meine Basepage für alle Seiten, die Benutzer benötigen Berechtigungen für den Zugriff sein. Die MandatoryPermissions sind Berechtigungen, die Benutzer müssen alle von ihnen haben auf die Seite zugreifen und OptionalPermissions sind Berechtigungen, die Benutzer zumindest einer von ihnen muss auf die Seite zuzugreifen. Es gibt keine Notwendigkeit, beide, weil auf jeder Seite zu verwenden, wenn Sie MandatoryPermissions haben keine Rolle, ob Sie die optionals haben oder nicht.

Genehmigung ist ein Enum:


public enum Permission 
{ 
    // Usually this enum will replicate a domain table from the database 
    EditUser = 1, 
    SearchUserByUsername = 2, 
    SearchUserByEmail = 3 

} 

Und MyUser ist eine Implementierung von MembershipUser:


public class MyUser : System.Web.Security.MembershipUser 
{ 
    internal bool HasPermission(Permission permission) 
    { 
     // 
     // TODO: Check on database if the user has the permission or not 
     // 
    } 
} 

Dann ist die einzige Sache, die Sie in Ihren Seiten tun müssen, ist die Berechtigungen Listen zu füllen:


public partial class EditUser : SecuredPage 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     MandatoryPermissions.Add(Permission.EditUser); 
    } 
} 

public partial class SearchUser : SecuredPage 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     OptionalPermissions.Add(Permission.SearchUserByUsername); 
     OptionalPermissions.Add(Permission.SearchUserByEmail); 
    } 
} 

OK, das Suchbeispiel war nicht so gut, aber ich denke, Sie bekommen das Bild.

Die ganze Idee ist, dass base.OnLoad(e); kurz vor der Überprüfung der Berechtigungen aufgerufen wird, so dass Sie nur die Berechtigungen in Ihrem Page_Load ausfüllen müssen.

Ich bin mir nicht sicher, ob dies die beste Lösung ist, aber ich bin sicher, dass es eine Menge :)

+0

Ich habe einen MembershipProvider und einen RoleProvider implementiert. Meine Fragen sind, wie Sie die Autorisierung von den einzelnen Seiten entkoppeln. Ich meine, setzen Sie eine Roles.IsInRole ("admin") in jede Ihrer Seiten? Verwenden Sie web.config Standortelemente? Oder haben Sie eine andere Möglichkeit, es von den Seiten zu entkoppeln? – JohannesH

+0

Ah, ok, also werde ich meine Antwort bearbeiten, um zu zeigen, wie ich es normalerweise tue :) Nur eine Sekunde – homemdelata

+0

Ja, der Ansatz der "Basisseite" ist das, was wir auch tun - eine Basisseite haben, die alle Authentifizierungen/Zugriffe behandelt Kontrolle, usw., und ein paar andere Funktionen, und erben dann die einzelnen Seiten davon. –

0

Haben Sie die GenericIdentity- und IPrincipal-Objekte während Ihrer Application_AuthenticateRequest-Methode der Anwendung eingerichtet?

Wir verwenden derzeit unsere Domäne, um Authentifizierung und Benutzergruppen/Rollen in der SQL Server-Datenbank zur Autorisierung bereitzustellen. Während der Application_AuthenticateRequest-Methode sammle ich alle diese Daten und erstelle ein FormsAuthenticationTicket-Objekt basierend darauf.

Dadurch habe ich jetzt Zugriff auf die Benutzerrollen, indem ich einen einfachen User.IsInRole ("RoleX") Befehl in meinem Code ausführe, der es mir ermöglicht, Benutzersteuerelemente einfach zu sperren/entsperren oder sogar eine einfache Antwort zu geben .Redirect() auf eine Seite "Authorization Error", wenn sie nicht die erforderliche Berechtigung haben.

Hier ist, was meine AuthenticateRequest Methode wie (VB.NET) sieht

Sub Application_AuthenticateRequest(ByVal sender As Object, _ 
             ByVal e As EventArgs) 

     Dim formsAuthTicket As FormsAuthenticationTicket 
     Dim httpCook As HttpCookie 
     Dim objGenericIdentity As GenericIdentity 
     Dim objMyAppPrincipal As CustomPrincipal 
     Dim strRoles As String() 

     httpCook = Context.Request.Cookies.Get("authCookieEAF") 
     formsAuthTicket = FormsAuthentication.Decrypt(httpCook.Value) 
     objGenericIdentity = New GenericIdentity(formsAuthTicket.Name) 
     strRoles = formsAuthTicket.UserData.Split("|"c) 
     objMyAppPrincipal = New CustomPrincipal(objGenericIdentity, strRoles) 
     HttpContext.Current.User = objMyAppPrincipal  

    End Sub 

... und in ähnlicher Weise, hier ist es, was das Objekt Custom wie folgt aussieht:

Public Class CustomPrincipal 
    Implements IPrincipal 


    ''' <summary> 
    ''' Identity object of user. 
    ''' </summary> 
    ''' <remarks></remarks> 
    Private m_identity As IIdentity 

    ''' <summary> 
    ''' Roles(s) a user is a part of. 
    ''' </summary> 
    ''' <remarks></remarks> 
    Private m_roles As String() 

    ''' <summary> 
    ''' Name of user. 
    ''' </summary> 
    ''' <remarks></remarks> 
    Private m_userId As String 

    ''' <summary> 
    ''' Gets/Sets the user name. 
    ''' </summary> 
    ''' <value>m_userId</value> 
    ''' <returns>Current name of user.</returns> 
    ''' <remarks></remarks> 
    Public Property UserId() As String 
     Get 
     Return m_userId 
     End Get 
     Set(ByVal value As String) 
     m_userId = value 
     End Set 
    End Property 

    ''' <summary> 
    ''' Gets the identity object of the user. 
    ''' </summary> 
    ''' <value>m_identity</value> 
    ''' <returns>Current identity of user.</returns> 
    ''' <remarks></remarks> 
    Public ReadOnly Property Identity() As System.Security.Principal.IIdentity Implements System.Security.Principal.IPrincipal.Identity 
     Get 
     Return m_identity 
     End Get 
    End Property 

    ''' <summary> 
    ''' Full constructor. 
    ''' </summary> 
    ''' <param name="identity">Identity to use with Custom Principal.</param> 
    ''' <param name="roles">Roles for user.</param> 
    ''' <remarks>Identity object contains user name when building constructor.</remarks> 
    Public Sub New(ByVal identity As IIdentity, ByVal roles As String()) 

     m_identity = identity 
     m_roles = New String(roles.Length) {} 
     roles.CopyTo(m_roles, 0) 
     Array.Sort(m_roles) 
     m_userId = identity.Name 

    End Sub 

    ''' <summary> 
    ''' Determines if the current user is in the role specified. 
    ''' </summary> 
    ''' <param name="role">Role to test against.</param> 
    ''' <returns>Boolean variable indicating if role specified exists in user's m_roles array.</returns> 
    ''' <remarks></remarks> 
    Public Function IsInRole(ByVal role As String) As Boolean Implements System.Security.Principal.IPrincipal.IsInRole 

     Dim boolResults As Boolean 

     If Array.BinarySearch(m_roles, role) >= 0 Then 
     boolResults = True 
     Else 
     boolResults = False 
     End If 

     Return boolResults 

    End Function 

End Class 

Hoffentlich gibt Ihnen, was Sie müssen Sie es in Ihre Umgebung einarbeiten.

+0

Wir haben die gleichen in unseren Anwendungen, da wir nur einen benutzerdefinierten Rollenanbieter und Mitgliedschaftsanbieter für die Authentifizierung und das Laden von Rollen verwenden. Was ich wirklich wissen möchte, ist, dass Sie dann eine User.IsInRole ("Admin") als erstes in page_init auf jeder Ihrer Admin-Seiten fest codieren. Oder haben Sie eine andere Möglichkeit, diese Konfiguration zu entkoppeln? Ich möchte keine Rollen- oder Azman-Regelnamen auf unseren Seiten fest codieren. – JohannesH

+0

Ich benutze eine Kombination aus web.config Autorisierung und Master-Vorlagen, um meine tatsächliche Code-Überprüfung auf ein Minimum zu halten. Ich habe auch einige Hilfsfunktionen wie "IsAdminAuthorized" und "IsManagerAuthorized", die die zusammengesetzten Überprüfungen durchführen, wenn Benutzer in mehreren verschiedenen Rollen als Administrator oder Manager qualifiziert sind. –

+0

Ok, mir scheint das ein wenig zu eng. Ich mag keine harte Codierung. Grundsätzlich denke ich, dass ich etwas wie das UrlAuthorization Modul machen muss. – JohannesH

1

Wie wäre es Mapping-Seiten zu Rollen in Ihrer Datenbank und dann lassen Sie Ihre Masterpage die DB überprüft auf Pageload hilft?

Verwandte Themen