我正在使用Castle Core创建自定义属性和拦截器,以使用属性将安全检查注入我们的代码中。 例如[安全(“角色1”)]
在拦截器的实现中:
public class SecurityInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
object o;
MethodInfo mi = invocation.Method;
SecurityAttribute[] atts = (SecurityAttribute[])mi.GetCustomAttributes(typeof(SecurityAttribute), true);
// if method not marked with Security attribute, then pass on call
if (atts.Length == 0)
{
invocation.Proceed();
}
else
{
//for now assume that there is only one security attribute on the method
//do some security test
{
invocation.Proceed();
}
}
}
在上面的“做一些安全性测试”部分中,我需要访问HttpContext.Session对象,以便检索一些保存的对象来进行安全性测试。
假设此属性所在的方法是一个代码隐藏的asp.net页面,即Page类的一个实例) 我不能只在这个属性中使用this.Context [Security(“Role1”,this.Context)] 因为属性不允许这样做。
那么如何在Intercept方法中访问httpContext?
或者有更好的方式以类似的方式这样做吗?
答案 0 :(得分:4)
InvocationTarget
实例的IInvocation
属性具有目标对象。因此,在您的情况下,如果您确定拦截发生在Page
对象上,您应该能够这样做:
var page = (Page)invocation.InvocationTarget;
如果情况并非总是如此,您应该以另一种方式访问HTTP上下文。
正如Ben指出的那样,HttpContext.Current
允许您从任何地方访问当前HttpContext
,但访问该静态属性只是icky。然而,有一种更好的方法,那就是注册一个允许注入会话状态的工厂方法:
container.Register(
Component.For<ISessionState>()
.UsingFactoryMethod(k => new SessionWrapper(HttpContext.Current.Session)
.Lifestyle.PerWebRequest));
假设您已经创建了ISessionState
接口和一个适当的包装器,该包装器具有您希望在与ASP.NET HttpSessionState
对象交互时使用的API。
现在,由于拦截器像容器一样从容器中拉出,它可能依赖于ISessionState
:
public class SecurityInterceptor : IInterceptor
{
public SecurityInterceptor(ISessionState sessionState)
{
//...
}
}
使你的拦截器变得美观和可测试。
可能有很多其他方法可以做到这一点,也可能有更好的方法。这只是关于如何继续项目的想法:)
答案 1 :(得分:1)
只要从ASP.net进程调用代码,您就可以在任何地方使用HttpContext.Current.Session
。