I'm currently investigating alternative solutions to the standard page authorization configuration in asp.net.
The location tag works ok if you have directories of files that need the same access policy but if you have lots of individual access policies the location tag is a pain. I could roll my own custom auth system but if it can be avoided thats probably better.
Currently we're using a azman-like permission based authorization system for page content but I haven't found a good way of integrating this with the standard page security yet.
Any suggestions on how to do this? Are there any solutions integrating azman and asp.net page authorization? Are there any other standard solutions I should be aware of?
I did in a huge application having lots of different permissions and different roles something like the following [I don't have the code here so I'll just try to recreate it here]:
I first implemented a class called SecuredPage as following:
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();
}
}
This will be my BasePage for all pages that user need permissions to access. The MandatoryPermissions
are permissions that user MUST have all of them to access the page and OptionalPermissions
are permissions that user needs at least one of them to access the page. There's no need to use both on every page because if you have MandatoryPermissions
doesn't matter if you have the optionals or not.
Permission is a enum:
public enum Permission
{
// Usually this enum will replicate a domain table from the database
EditUser = 1,
SearchUserByUsername = 2,
SearchUserByEmail = 3
}
And MyUser
is a implementation of 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
//
}
}
Then the only thing that you need to do in your pages is to populate the permissions lists:
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, the search example wasn't that good but I think you get the picture.
The whole idea is that base.OnLoad(e);
is called just before the permissions verification, so you just need to fill the permissions in your Page_Load
.
I'm not sure if this is the best solution but I'm sure it helps a lot :)
如何将页面映射到数据库中的角色,然后让您的母版页检查页面上的数据库?
Have you setup the GenericIdentity and IPrincipal objects during your Application_AuthenticateRequest method of the application?
We currently use our domain to do authentication and user groups/roles on the SQL Server database to provide authorization. During the Application_AuthenticateRequest method, I gather all this data and create a FormsAuthenticationTicket object based on it.
By doing so, I now have access to the user's roles by performing a simple User.IsInRole("RoleX") command in my code, which allows me to easily lock/unlock user controls, or even do a simple Response.Redirect() to a "Authorization Error" page if they don't have the proper authorization.
Here's what my AuthenticateRequest method looks like (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
...and similarly, here's what the CustomPrincipal object looks like:
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
Hopefully this gives you what you need to mold it into your environment.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.