Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 使用Castle Windsor在IAuthenticationManager中注册OWIN_.net_Castle Windsor_Owin_Katana_Owin Security - Fatal编程技术网

.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())