Так что после некоторого исследования, я думаю, я нашел чистый способ сквозного обеспечения безопасности с помощью перехвата Unity.Я поделюсь своим кодом:
public class MyCallHandler: ICallHandler
{
private readonly string[] roles;
public MyCallHandler(params string[] roles)
{
this.roles = roles;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IPrincipal principal = Thread.CurrentPrincipal;
bool allowed = roles.Any(principal.IsInRole);
if (!allowed)
return input.CreateExceptionMethodReturn(new
Exception("Security exception!"));
return getNext()(input, getNext);
}
public int Order
{
get;
set;
}
}
public class MethodAccessAttribute : HandlerAttribute
{
private readonly string[] roles;
public MethodAccessAttribute(params string[] roles)
{
this.roles = roles;
}
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new MyCallHandler(roles);
}
}
public interface IConsoleThingie
{
[MethodAccess("admin")]
void SomeMethod();
}
public class MyConsoleThing : IConsoleThingie
{
public void SomeMethod()
{
Console.WriteLine("test");
}
}
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<IConsoleThingie, MyConsoleThing>().Configure<Interception>().SetInterceptorFor<IConsoleThingie>(new InterfaceInterceptor());
IConsoleThingie thing = container.Resolve<IConsoleThingie>();
try
{
thing.SomeMethod();
}
catch
{
Console.WriteLine("More granular exception handling here");
Console.ReadLine();
}
}
}
Как вы можете видеть, все дело в создании пользовательского атрибута HandlerAttribute, который в свою очередь вызывает пользовательский ICallHandler.В CallHandler вы можете поместить свою логику, связанную с безопасностью, которая будет определять, будет ли выполнен декорированный метод.Вы должны выдать несколько пользовательских исключений, которые вы можете поймать из слоя, используя ваши методы.Имея эту инфраструктуру, вы можете без проблем интегрировать любые сквозные модули.Вот конфигурация для приложения, так как это может быть немного болезненно в Unity.Не забудьте добавить пространство имен Microsoft.Practices.Unity.InterceptionExtension в ваши классы, кстати.
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
<containers>
<container>
<extension type="Interception" />
<register type="IConsoleThingie" mapTo="MyConsoleThing">
<interceptor type="InterfaceInterceptor" />
<policyInjection />
</register>
<types>
</types>
</container>
</containers>
</unity>
</configuration>