我目前正在研究 asp.net 中标准页面授权配置的替代解决方案。
如果您有需要相同访问策略的文件目录,则位置标签可以正常工作,但如果您有很多单独的访问策略,则位置标签很麻烦。我可以推出自己的自定义身份验证系统,但如果可以避免,那可能会更好。
目前,我们正在为页面内容使用类似 azman 的基于权限的授权系统,但我还没有找到一种将其与标准页面安全性集成的好方法。
关于如何做到这一点的任何建议?有没有集成 azman 和 asp.net 页面授权的解决方案?还有其他我应该注意的标准解决方案吗?
我目前正在研究 asp.net 中标准页面授权配置的替代解决方案。
如果您有需要相同访问策略的文件目录,则位置标签可以正常工作,但如果您有很多单独的访问策略,则位置标签很麻烦。我可以推出自己的自定义身份验证系统,但如果可以避免,那可能会更好。
目前,我们正在为页面内容使用类似 azman 的基于权限的授权系统,但我还没有找到一种将其与标准页面安全性集成的好方法。
关于如何做到这一点的任何建议?有没有集成 azman 和 asp.net 页面授权的解决方案?还有其他我应该注意的标准解决方案吗?
我在一个巨大的应用程序中做了很多不同的权限和不同的角色,如下所示[我这里没有代码,所以我将尝试在这里重新创建它]:
我首先实现了一个名为 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
}
并且MyUser是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
//
}
}
然后,您需要在页面中做的唯一一件事就是填充权限列表:
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.
我不确定这是否是最好的解决方案,但我相信它有很大帮助:)
如何将页面映射到数据库中的角色,然后让您的母版页在页面加载时检查数据库?
您是否在应用程序的 Application_AuthenticateRequest 方法期间设置了 GenericIdentity 和 IPrincipal 对象?
我们目前使用我们的域在 SQL Server 数据库上进行身份验证和用户组/角色以提供授权。在 Application_AuthenticateRequest 方法中,我收集所有这些数据并基于它创建一个 FormsAuthenticationTicket 对象。
通过这样做,我现在可以通过在我的代码中执行一个简单的 User.IsInRole("RoleX") 命令来访问用户的角色,这使我可以轻松地锁定/解锁用户控件,甚至可以执行一个简单的 Response.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
希望这为您提供了将其塑造到您的环境中所需的东西。