2009-04-24 74 views
4

我目前正在調查asp.net中標準頁面授權配置的替代解決方案。ASP.NET頁面授權...你怎麼做到的?

如果您有需要相同訪問策略的文件的目錄,但是如果您有許多單獨的訪問策略,位置標記是一種痛苦,則位置標記可以正常工作。我可以推出我自己的自定義認證系統,但如果可以避免這可能會更好。

目前我們對頁面內容使用基於azman的權限授權系統,但是我還沒有找到將此與標準頁面安全性集成的好方法。

有關如何做到這一點的任何建議?有沒有任何解決方案集成azman和asp.net頁面授權?是否還有其他標準解決方案應該注意?

回答

6

我有很多不同的權限和不同的角色類似於下面的[我沒有代碼在這裏,所以我會只是試圖在這裏重建吧]的巨大的應用做了一個名爲SecuredPage的類如下所示:


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(); 
    } 
} 

這將是我的BasePage,用於需要用戶訪問權限的所有頁面。 MandatoryPermissions是用戶必須讓他們全部訪問該頁面的權限,而用戶至少需要其中一個用戶訪問該頁面的權限是OptionalPermissions。 因爲如果您有MandatoryPermissions沒有必要在每個頁面上都使用,因爲如果您有選擇權或不。

權限是枚舉:


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

} 

而且MyUserMembershipUser一個實現:


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

然後,你需要在你的網頁做的唯一的事情是填充的權限列表:


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); 
    } 
} 

好的,搜索範例不是很好,但我認爲你可以得到圖片。

整個想法是在權限驗證之前調用base.OnLoad(e);,因此您只需填寫Page_Load中的權限即可。

我不知道這是否是最好的解決辦法,但我敢肯定,它幫助了很多:)

0

您是否在應用程序的Application_AuthenticateRequest方法期間設置了GenericIdentity和IPrincipal對象?

我們目前使用我們的域在SQL Server數據庫上執行身份驗證和用戶組/角色以提供授權。在Application_AuthenticateRequest方法期間,我收集所有這些數據並基於它創建一個FormsAuthenticationTicket對象。

通過這樣做,我現在可以通過在我的代碼中執行一個簡單的User.IsInRole(「RoleX」)命令來訪問用戶的角色,這使我可以輕鬆地鎖定/解鎖用戶控件,甚至做一個簡單的響應.Redirect()到一個「授權錯誤」頁面,如果他們沒有適當的授權。

這裏就是我的AuthenticateRequest方法看起來像(VB.NET)

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 

......同樣,這裏的CustomPrincipal對象是什麼樣子:

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 

但願這給你什麼你需要將它塑造成你的環境。

我第一次執行:

+0

我們在我們的應用程序中使用相同的方法,我們只是使用自定義角色提供者和成員資格提供程序進行身份驗證和角色加載。 我真正想知道的是,您是否在User_IsInRole(「Admin」)中對每個管理頁面的page_init中的第一件事進行了硬編碼。或者你有其他解耦方式嗎?我不想將角色或azman規則名稱硬編碼到我們的頁面中。 – JohannesH 2009-04-24 22:41:27

+0

我使用web.config授權和主模板的組合來將我的實際代碼檢查降到最低。我還有一些輔助功能,如「IsAdminAuthorized」和「IsManagerAuthorized」,當幾個不同角色的用戶有資格擔任管理員或經理時,可以進行組合檢查。 – 2009-04-25 00:04:56

1

如何映射到頁面數據庫中的角色,然後讓你的母版檢查DB的頁面加載?