用SignalR注入IPrincipal

时间:2014-12-15 12:47:09

标签: c# dependency-injection signalr owin iprincipal

我正在尝试将IPrincipal注入我的SignalR中心构建器。 我已经看过并尝试过“Selective IPrincipal Injection via StructureMap with SignalR”的解决方案,但不幸的是,这似乎不再适用于SignalR 2.x.

在我的调试中,我发现有时,我的集线器构造函数在堆栈中使用我的OWIN中间件调用。在这种情况下,Thread.CurrentPrincipal是正确的值。另外(并且令人惊讶地),HttpContext.Current也不为空。我的印象是在SignalR中它始终为空,我不是试图使用它,但我只是在观察。似乎这些调用的调用来自调用堆栈中的管道。

其他时候,调用似乎来自线程池。在这些情况下,Thread.CurrentPrincipalGenericPrincipalHttpContext.Current为空(再次只是观察),而我似乎无法静态获取主体。但是,在集线器内部,this.Context.User属性 具有正确的主体。

我怎样才能静态获取主体,以便将其注入中心构造函数?

3 个答案:

答案 0 :(得分:1)

当SignalR Hubs被激活时,有时会设置HttpContext.CurrentThread.CurrentPrincipal,但并非总是如此。这是因为激活线程经常与ASP.NET SynchronizationContext一起运行。在某些情况下,情况并非如此,例如,为了处理WebSocket消息或不干净的OnDisconnected事件而激活集线器。长话短说,有时这些静力学恰好存在,但你不能依赖它。

我不知道如何可靠地静态获取IPrincipal。在你的Hub中使用Context.User有什么问题?

答案 1 :(得分:1)

如果我理解了您正在尝试做的事情......您应该构建自己的Authorize属性,将自定义主体放入特殊的Owin变量中,然后在Context.User中访问它在集线器内。

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
    {
        //put our custom user-principal into a magic "server.User" Owin variable
        request.Environment["server.User"] = new MyCustomPrincipal(); //<!-THIS!

        return base.AuthorizeHubConnection(hubDescriptor, request);
    }
}

然后将此属性应用于您的Hub。

如果您想了解更多相关信息,我在博文中提到了here以及更多代码示例

答案 2 :(得分:0)

我试图解决同样的问题,我找到了设置用户身份的解决方案。

我的应用程序受到saml保护,客户端应用程序发送&#34; SAML&#34;令牌作为标题的一部分。我们编写了Asp.net模块来验证令牌并准备用户身份并为响应标头添加值。

我创建了OwinStartup类,并使用下面的代码添加了我自己的请求处理器。 我已经为Longpolling测试了这段代码并且工作正常。我不确定它是如何工作的,#34; WebScoket&#34;。

 public void Configuration(IAppBuilder app)
    {
        // Any connection or hub wire up and configuration should go here           
        try
        {
            app.Use(SetMyPrincipalObject);
        }
    }

  private Task SetMyPrincipalObject(IOwinContext arg1, Func<Task> arg2)
    {
        //var p = "Process response";//Process Response Header here and //create identity
        //arg1.Request.User = p;
        //return arg2.Invoke();
    }