.net 使用Castle Windsor在IAuthenticationManager中注册OWIN
由于.net 使用Castle Windsor在IAuthenticationManager中注册OWIN,.net,castle-windsor,owin,katana,owin-security,.net,Castle Windsor,Owin,Katana,Owin Security,由于IAuthenticationManager实现可以从OWIN上下文中检索,但Castle Windsor的组件注册必须在解析组件之前完成,因此如何将IAuthenticationManager注册为组件以在任何地方注入 好的,我应该使用Component.For().UsingFactoryMethod(…),但是由于我使用的是OWIN/Katana,类似于HttpContext.Current.GetOwinContext()的东西将不起作用(如果它能起作用,我不愿意为此向System.
IAuthenticationManager
实现可以从OWIN上下文中检索,但Castle Windsor的组件注册必须在解析组件之前完成,因此如何将IAuthenticationManager
注册为组件以在任何地方注入
好的,我应该使用Component.For().UsingFactoryMethod(…)
,但是由于我使用的是OWIN/Katana,类似于HttpContext.Current.GetOwinContext()
的东西将不起作用(如果它能起作用,我不愿意为此向System.Web
添加依赖项)
目前的解决方案是什么 暂时(或最终)解决方案。。。
我就是这样设法解决这个问题的
首先,我实现了一个简单的OWIN中间件:
public sealed class WindsorMiddleware : OwinMiddleware
{
public WindsorMiddleware(OwinMiddleware next) : base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
CallContext.LogicalSetData("owinContext", context);
await Next.Invoke(context);
CallContext.FreeNamedDataSlot("owinContext");
}
}
我已经使用组件注册配置了iaauthenticationmanager
。UseFactoryMethod,因此我实现了如下扩展方法:
public static ComponentRegistration<TService> UseOwinComponentFactoryMethod<TService>(this ComponentRegistration<TService> registration)
where TService : class
{
return registration.UsingFactoryMethod
(
(kernel, componentModel, creationContext) =>
{
IOwinContext owinContext = CallContext.LogicalGetData("owinContext") as IOwinContext;
Contract.Assert(owinContext != null);
if (creationContext.RequestedType == typeof(IAuthenticationManager))
{
return (TService)owinContext.Authentication;
}
else
{
throw new NotSupportedException();
}
},
managedExternally: true
);
}
闻起来。。。
顺便说一句,我不相信这个解决方案的可靠性,因为除非您尝试在请求线程之外的另一个线程中解析组件,否则这个解决方案应该可以工作
不幸的是,在很多情况下,这种解决方案都可能失败。如果您的代码实现了非阻塞I/O,我希望尝试从另一个线程注入IAuthenticationManager
,该线程在CallContext
中设置了“owinContext”
在我找到更好、更优雅的解决方案的同时,我仍然会期待其他答案。对于那些不介意依赖于
System.Web
的人来说,以下代码应该可以工作(并且不需要中间件)
然后在您的castle windsor安装程序中:
container.Register(Component.For<IAuthenticationManager>()
.UsingFactoryMethod(GetAuthenticationManager, managedExternally: true)
.LifestyleTransient())
container.Register(Component.For())
.UsingFactoryMethod(GetAuthenticationManager,ManagedExternaly:true)
.LifestyleTransient())
为什么说HttpContext.Current.GetOwinContext()
不起作用?@PhilDegenhardt我使用的是OWIN/Katana。您可能需要添加managedExternaly:true
UsingFactoryMethod()的参数要明确的是,温莎不负责申请任何佣金/退役问题。看来卡塔纳的DI故事相当糟糕。它在ASP.NET 5中得到了彻底的改进,这应该会有所改进:@PhilDegenhardt感谢您的建议。我不知道这门课。已经一年多了。您是否仍在使用此实现从Windsor Castle访问OWIN上下文?@MatíasFidemrAzer我尝试了您的代码,但当UseOWIncomonentFactoryMethod()扩展方法执行时,IOwinContext owinContext=CallContext.LogicalGetData(“owinContext”)作为IOwinContext代码>返回空值。我正在Startup.cs中注册windsormidware
,就像这样:app.Use(typeof(windsormidware))代码>。但是,例如,在Katana托管的API中,您会获得HttpContext.Current
assigned吗\@MatíasFidemraizer是的,我忘了你不能依赖HtppContext.Current。我正在使用IIS,因此上面的代码对我有效。不过这一点很好。
private static IAuthenticationManager GetAuthenticationManager(IKernel kernel, ComponentModel componentModel, CreationContext creationContext)
{
var owinContext = new HttpContextWrapper(HttpContext.Current).GetOwinContext();
return owinContext.Authentication;
}
container.Register(Component.For<IAuthenticationManager>()
.UsingFactoryMethod(GetAuthenticationManager, managedExternally: true)
.LifestyleTransient())