开发者

fine-grained permissions; PrincipalPermission - roles seperate from permissions;

开发者 https://www.devze.com 2022-12-29 04:32 出处:网络
I\'ve been using PrincipalPermission for a while in wcf services. [PrincipalPermission(SecurityAction.Demand, Role = SecurityRoles.CanManageUsers)]

I've been using PrincipalPermission for a while in wcf services. [PrincipalPermission(SecurityAction.Demand, Role = SecurityRoles.CanManageUsers)]

Our roles are prefixed with: Can* and is how we achieve fine grained actions control with the built in asp.net membership system.

This makes it hard to k开发者_开发百科now as a business unit what fine grained roles we can give to a user.

Here is my new approach and wanted to see if anyone can provide feedback, code review before i implement my suggestion.

1) aspnet_roles - business unit role

2) Extend the asp.net membership system by creating a permission table and Role_Permission table and User_Permission table (many to many)

3) create custom CodeAccessSecurityAttribute + that looks at new tables [CustomPermissionCheck(Security.Demand, HasPermission="can*")] first iteration i'll statically new the dependent repository.. ideally i would like an aop style attribute that has repository injected IPermissionRepository.HasPermission(...);

If i approach new aop way i probably will stop inheriting from CodeAccessSecurityAttribute -- what do the security guys have to say about this?

has anyone else solved this, is there something in the framework that i've missed?


I would say that if you are in ASP.NET, then you should implement a custom RoleProvider.

In your custom RoleProvider, you would access another table which would have the business groups linked to the fine grained permissions.

Then, when you find out the user, you can find out the business group that they are in and assign all of the appropriate roles in the RoleProvider and not change any of the existing code that you have.

It also works better, because it allows you to change what groups have what permissions easily, while keeping the domain model for permissions pure on the code side.


I implemented first iteration and it is working nicely. [PermissionValidate(SecurityAction.Demand, HasPermission = CensusSchedulerRoles.CanUpdateCensusScheduler)]

public void Demand()
{
    var principal = Thread.CurrentPrincipal;
    if(principal == null || principal.Identity.IsAuthenticated == false)
    {
        throw new SecurityException("Unable to get IPrincipal.");
    }
    if(principal.Identity.IsAuthenticated == false)
    {
        throw new SecurityException("You must be authenticated.");
    }   
     #warning this should be moved to an aop attribute that is injected by a ioc container.
    using (var connection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["......."].ConnectionString))
    {
        connection.Open();
        using(var command = new SqlCommand(
        @"
            SELECT COUNT(t.name) FROM
            (
                SELECT p.name, u.UserName FROM 
                    aspnet_Users as u
                    INNER JOIN [User_Permission] as up
                        ON up.user_id = u.UserId
                    INNER JOIN Permission as p
                        ON p.id = up.permission_id
                UNION
                SELECT p2.name, u2.UserName FROM 
                    aspnet_Users as u2
                    INNER JOIN aspnet_UsersInRoles as uir
                        ON uir.UserId = u2.UserId
                    INNER JOIN aspnet_Roles as r
                        ON r.RoleId = uir.RoleId
                    INNER JOIN Role_Permission as rp
                        ON rp.role_id = r.RoleId
                    INNER JOIN Permission as p2
                        ON p2.id = rp.permission_id
            ) as t
            WHERE t.UserName = @username AND t.name = @haspermission
        ", connection))
        {
            command.Parameters.Add("@username", SqlDbType.VarChar).Value = Thread.CurrentPrincipal.Identity.Name;
            command.Parameters.Add("@haspermission", SqlDbType.VarChar).Value = _permissionRequested;

            if( Convert.ToInt32(command.ExecuteScalar()) <=0)
            {
                throw new SecurityException(String.Format("User '{0}' is not assigned permission '{1}'.", principal.Identity.Name, _permissionRequested));
            }
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号