细粒度的权限; PrincipalPermission - 角色与权限分开;

时间:2010-05-03 18:11:40

标签: c# wcf security code-access-security principalpermission

我一直在wcf服务中使用PrincipalPermission一段时间。 [PrincipalPermission(SecurityAction.Demand,Role = SecurityRoles.CanManageUsers)]

我们的角色前缀为:Can *和我们如何通过内置的asp.net会员系统实现细粒度的动作控制。

这使我们很难知道我们可以为用户提供哪些细粒度的角色作为业务部门。

这是我的新方法,想看看在实施我的建议之前是否有人可以提供反馈,代码审查。

1)aspnet_roles - 业务单位角色

2)通过创建权限表和Role_Permission表以及User_Permission表(多对多)来扩展asp.net成员资格系统

3)创建查看新表的自定义CodeAccessSecurityAttribute + [CustomPermissionCheck(Security.Demand,HasPermission =“can *”)] 第一次迭代我将静态地新建依赖存储库..理想情况下,我想要一个具有存储库注入的aop样式属性IPermissionRepository.HasPermission(...);

如果我采用新的方式,我可能会停止从CodeAccessSecurityAttribute继承 - 安全人员对此有什么看法?

有没有其他人解决过这个问题,框架中有什么东西我错过了吗?

2 个答案:

答案 0 :(得分:0)

我想说如果你在ASP.NET中,那么你应该实现custom RoleProvider

在您的自定义RoleProvider中,您将访问另一个表,该表将业务组链接到细粒度权限。

然后,当您找到用户时,您可以找到他们所在的业务组,并在RoleProvider中分配所有相应的角色,而不是更改您拥有的任何现有代码。

它也可以更好地工作,因为它允许您轻松更改哪些组具有哪些权限,同时保持域模型的权限纯粹在代码端。

答案 1 :(得分:0)

我实现了第一次迭代,它运行良好。 [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));
            }
        }
    }
}