Мелкозернистые разрешения; PrincipalPermission - роли, отделенные от разрешений;

Я некоторое время использовал PrincipalPermission в сервисах wcf. [PrincipalPermission(SecurityAction.Demand, Role = SecurityRoles.CanManageUsers)]

Наши роли имеют префикс: Can* и это то, как мы добиваемся тонкого контроля действий с помощью встроенной системы членства asp.net.

Это затрудняет понимание как бизнес-единицы, какие тонко детализированные роли мы можем дать пользователю.

Вот мой новый подход, и я хотел посмотреть, сможет ли кто-нибудь дать отзыв, пересмотреть код, прежде чем я реализую свое предложение.

1) aspnet_roles - роль бизнес-единицы

2) Расширить систему членства asp.net, создав таблицу разрешений и таблицу Role_Permission и таблицу User_Permission (многие ко многим)

3) создать пользовательский CodeAccessSecurityAttribute +, который просматривает новые таблицы [CustomPermissionCheck(Security.Demand, HasPermission="can*")] первая итерация, я статически создаю новый зависимый репозиторий.. в идеале я хотел бы, чтобы атрибут стиля aop вставлял репозиторий IPermissionRepository.HasPermission(...);

Если я подойду по-новому, я, вероятно, перестану наследовать от CodeAccessSecurityAttribute - что по этому поводу скажут парни из службы безопасности?

кто-нибудь еще решил это, есть что-то в рамках, что я пропустил?

2 ответа

Я реализовал первую итерацию, и она работает хорошо. [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));
            }
        }
    }
}

Я бы сказал, что если вы находитесь в ASP.NET, то вам следует реализовать собственный RoleProvider.

В вашем пользовательском RoleProvider вы получите доступ к другой таблице, в которой бизнес-группы будут связаны с детализированными разрешениями.

Затем, когда вы узнаете пользователя, вы можете выяснить, в какой бизнес-группе он находится, и назначить все соответствующие роли в RoleProvider, а не изменять имеющийся у вас код.

Это также работает лучше, потому что позволяет легко изменять какие группы имеют какие разрешения, сохраняя при этом модель домена для разрешений чисто на стороне кода.

Другие вопросы по тегам