Почему Custom SecurityPermission не загружается? - PullRequest
7 голосов
/ 13 мая 2011

Я создал реализацию CodeAccessSecurityAttribute, которая использует информацию стека для поиска имени целевого класса, но в некоторых классах PrincipalPermition не создается, вместо этого система использует превью. Что я упустил?

[ComVisible(true)]
[AttributeUsageAttribute(AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = true, Inherited = false)] 
public sealed class MyPrincipalPermissionAttribute : CodeAccessSecurityAttribute
{
    public MyPrincipalPermissionAttribute(SecurityAction action) : base(action) { }

    public override IPermission CreatePermission()
    {
        if (Unrestricted)
            return new PrincipalPermission(PermissionState.Unrestricted);
        var stackTrace = new StackTrace();

        var fullnameArray = new List<String>();
        foreach (var frame in stackTrace.GetFrames())
        {
            try
            {
                var method = frame.GetMethod();
                if (method != null && method.ReflectedType.IsSubclassOf(typeof (BaseClass)))
                    fullnameArray.Add(method.ReflectedType.FullName);
            } catch {}
        }

        if (fullnameArray.Count() > 0)
            return new PrincipalPermission(null, fullnameArray[0], true);

        return new PrincipalPermission(PermissionState.Unrestricted);
    }
}

И использование

public class MyClassCalledFirstWork: BaseClass
{
    [MyPrincipalPermission(SecurityAction.Demand)]
    public override void DoSomething()
    {
        return;
    }
}

public class MyClassCalledSecondDontWork: BaseClass
{
    [MyPrincipalPermission(SecurityAction.Demand)]
    public override void DoSomething()
    {
        return;
    }
}

1 Ответ

1 голос
/ 01 июля 2011

Это из документации для SecurityAttribute.CreatePermission ():

"Метод CreatePermission создает объект разрешения, который затем может быть сериализованный в двоичную форму и постоянно хранятся вместе с SecurityAction в собрании метаданные. "

"Во время компиляции атрибуты конвертируют безопасность объявления в сериализованную форму в метаданные. Декларативная защита данных в метаданные создаются из разрешение, что этот метод возвращает что соответствует этому атрибуту. "

Похоже, что может быть только один объект разрешения (некоторого типа), соответствующий пользовательскому атрибуту CodeAccessSecurityAttribute, сохраненному для определенного SecurityAction. Когда вы проверяете IL для методов DoSomething, вы видите, что они содержат идентичные требования к разрешениям с ролью, определенной во время первого вызова CreatePermission.

.method public hidebysig virtual instance void 
        DoSomething() cil managed
{
    .permissionset demand
             = {class 'CustomSecurityPermission.Program+MyPrincipalPermissionAttribute, CustomSecurityPermission, Version=1.0.0.0, Culture=neutral' = {}}
    ...
} // end of method MyClassCalledSecondDontWork::DoSomething

.method public hidebysig virtual instance void 
        DoSomething() cil managed
{
    .permissionset demand
             = {class 'CustomSecurityPermission.Program+MyPrincipalPermissionAttribute, CustomSecurityPermission, Version=1.0.0.0, Culture=neutral' = {}}
    ...
} // end of method MyClassCalledFirstWork::DoSomething

Ответ на ваш второй вопрос из комментариев:
Вместо использования декларативного CAS я бы использовал императив:

public sealed class Security
{
    public static IPermission CreatePermission()
    {
        var stackTrace = new StackTrace();

        var fullnameArray = new List<String>();
        foreach (var frame in stackTrace.GetFrames())
        {
            try
            {
                var method = frame.GetMethod();
                if (method != null && method.ReflectedType.IsSubclassOf(typeof(BaseClass)))
                    fullnameArray.Add(method.ReflectedType.FullName);
            }
            catch { }
        }
        if (fullnameArray.Count() > 0)
        {
            return new PrincipalPermission(null, fullnameArray[0]);
        }
        return new PrincipalPermission(PermissionState.Unrestricted);
    }
}

public class MyClassCalledFirstWork : BaseClass
{
    public override void DoSomething()
    {
        Security.CreatePermission().Demand();
        return;
    }
}

public class MyClassCalledSecondDontWork : BaseClass
{
    public override void DoSomething()
    {
        Security.CreatePermission().Demand();
        return;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...