Пользовательский CodeAccessSecurityattribute, который занимает много ролей

StackOverflow https://stackoverflow.com/questions/8358503

Вопрос

Я работаю над какой-то на основе роли безопасности для нашего приложения, и я по сути хочу сделать индивидуальную Verison MVC AuthorizeAttribute - Но только на слое бизнес -логики, где мы не ссылаемся на MVC.

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

Есть ли в .net есть что -то подобное ?NET, которое мне не хватает? Или у кого -нибудь есть некоторое представление о том, как сделать это без повторного повторного представления ASP.NET AuthorizeAttribute/RoleProvider/и т. Д.?

РЕДАКТИРОВАТЬ

В настоящее время у меня есть императивная версия, но я бы предпочел иметь версию декларативного атрибута, так как легче увидеть ее выше метода/класса.

Прямо сейчас у меня есть следующее в абстрактном базовом классе для моего бизнес -слоя:

protected void EnsureEditorLevelAccess()
{
    var allowedRoles = new[]
                            {
                                Roles.Administrator,
                                Roles.Editor,
                            };

    var roles = GetAccountRoles(GetCurrentUsername());

    if (roles.Any(role => allowedRoles.Contains(role)))
    {
        return;
    }

    throw new SecurityException("You do not have sufficient privileges for this operation.");
}

Мне нравится использовать Roles.Administrator и т. Д. Потому что названия ролей являются отвратительными (на основе группы Active Directory ...), поэтому я думал о том, чтобы завершить эти детали в конструкторе пользовательского атрибута, который я могу просто подтолкнуть к классам/методам.

GetAccountRoles это всего лишь фасад над свойством инъекционного ролевого провалора, которое я могу использовать для использования либо AD, либо версии тестирования, которая использует базу данных.

Я мог бы подкласс Attribute, но не уверен, как это начало проверку безопасности.

Это было полезно?

Решение

Вы можете создать новый атрибут, в котором используется существующая принципиальная передача, если этого будет достаточным для ваших нужд. Если ваша существующая императивная реализация использует PrincipPermission, то это должно быть так. Однако, если ваша императивная версия делает что -то еще, вам, возможно, потребуется рассмотреть возможность реализации как пользовательского разрешения, так и соответствующего атрибута. Если вы не уверены, необходимо ли это, возможно, вы можете поделиться некоторыми подробностями относительно вашего нынешнего императивного подхода ...


После обновления вопросов ...

На самом деле можно использовать «любую» логику с принципиальным контролем, хотя она требует объединения нескольких случаев, с которыми не особенно практично работать в атрибуте. Это делает гораздо более разумным создание пользовательского атрибута, который может выглядеть примерно как следующее:

[Serializable]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class AnyRolePermissionAttribute : CodeAccessSecurityAttribute
{
    public AnyRolePermissionAttribute(SecurityAction action)
        : base(action)
    {
    }

    public string Roles { get; set; }

    public override IPermission CreatePermission()
    {
        IList<string> roles = (this.Roles ?? string.Empty).Split(',', ';')
                                .Select(s => s.Trim())
                                .Where(s => s.Length > 0)
                                .Distinct()
                                .ToList();

        IPermission result;
        if (roles.Count == 0)
        {
            result = new PrincipalPermission(null, null, true);
        }
        else
        {
            result = new PrincipalPermission(null, roles[0]);
            for (int i = 1; i < roles.Count; i++)
            {
                result = result.Union(new PrincipalPermission(null, roles[i]));
            }
        }

        return result;
    }
}

К сожалению, вы не можете использовать массивы в атрибутах безопасности, поэтому список ролей должен быть представлен как строка. например:

[AnyRolePermission(SecurityAction.Demand, Roles = "Foo, Bar")]

Вы можете использовать его с константами с помощью конкатенации времени дизайна. например:

[AnyRolePermission(SecurityAction.Demand, Roles = Roles.Administrator + ", " + Roles.Editor)]

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

Другие советы

Вы можете получить свою собственную CodeAccessSecurityAttribute и реализовать свою логику вокруг Thread.currentPrincipal (http://msdn.microsoft.com/en-us/library/system.security.permissions.codeaccesssecurityattribute.aspx).

по сути, вы хотели бы проверить allowedRoles.Any(r => Thread.CurrentPrincipal.IsInRole(r))

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top