【问题标题】:ASP.NET Page Authorization... How do you do it?ASP.NET 页面授权...你是怎么做到的?
【发布时间】:2010-10-21 17:23:46
【问题描述】:

我目前正在研究 asp.net 中标准页面授权配置的替代解决方案。

如果您有需要相同访问策略的文件目录,则位置标签可以正常工作,但如果您有很多单独的访问策略,则位置标签会很麻烦。我可以推出自己的自定义身份验证系统,但如果可以避免,那可能会更好。

目前我们正在使用类似 azman 的基于权限的页面内容授权系统,但我还没有找到将其与标准页面安全性集成的好方法。

关于如何做到这一点的任何建议?有没有集成 azman 和 asp.net 页面授权的解决方案?还有其他我应该注意的标准解决方案吗?

【问题讨论】:

    标签: .net asp.net security authorization


    【解决方案1】:

    我在一个具有许多不同权限和不同角色的大型应用程序中进行了如下操作[我这里没有代码,所以我将尝试在此处重新创建它]:

    我首先实现了一个名为 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();
        }
    }
    

    这将是用户需要访问权限的所有页面的基本页面。 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中填写权限即可。

    我不确定这是否是最好的解决方案,但我相信它很有帮助:)

    【讨论】:

    • 我已经实现了一个 MembershipProvider 和一个 RoleProvider。我的问题是如何将授权与各个页面分离。我的意思是,您是否在每个页面中都放置了 Roles.IsInRole("admin") ?你使用 web.config 位置元素吗?或者您有其他方法可以将其与页面分离吗?
    • 啊,好的,所以我将编辑我的答案以显示我通常的做法:) 等一下
    • 是的,“基本页面”类型的方法也是我们所做的 - 拥有一个处理所有身份验证/访问控制等的基本页面,以及一些其他功能,然后继承各个页面从那。
    【解决方案2】:

    如何将页面映射到数据库中的角色,然后让母版页在页面加载时检查数据库?

    【讨论】:

      【解决方案3】:

      您是否在应用程序的 Application_AuthenticateRequest 方法期间设置了 GenericIdentity 和 IPrincipal 对象?

      我们目前使用我们的域在 SQL Server 数据库上进行身份验证和用户组/角色以提供授权。在 Application_AuthenticateRequest 方法中,我收集所有这些数据并基于它创建一个 FormsAuthenticationTicket 对象。

      通过这样做,我现在可以通过在我的代码中执行一个简单的 User.IsInRole("RoleX") 命令来访问用户的角色,这使我可以轻松地锁定/解锁用户控件,甚至执行一个简单的响应。如果他们没有适当的授权,则重定向()到“授权错误”页面。

      这是我的 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
      

      希望这可以为您提供将其融入您的环境所需的东西。

      【讨论】:

      • 我们在我们的应用程序中具有相同的功能,但我们只是使用自定义角色提供程序和成员资格提供程序进行身份验证和角色加载。我真正想知道的是,您是否将 User.IsInRole("Admin") 硬编码为每个管理页面上 page_init 中的第一件事。还是您有其他方法可以解耦此配置?我不想将角色或 azman 规则名称硬编码到我们的页面中。
      • 我结合使用 web.config 授权和主模板来将我的实际代码检查降至最低。我还有几个辅助函数,例如“IsAdminAuthorized”和“IsManagerAuthorized”,当多个不同角色的用户有资格成为管理员或经理时,它们会进行复合检查。
      • 好的,对我来说这似乎有点太耦合了。我不喜欢硬编码。基本上我认为我需要制作类似 UrlAuthorization 模块的东西。
      猜你喜欢
      • 1970-01-01
      • 2012-08-27
      • 1970-01-01
      • 1970-01-01
      • 2010-09-11
      • 1970-01-01
      • 1970-01-01
      • 2011-12-18
      • 2010-11-18
      相关资源
      最近更新 更多