我使用SignalR 1.0.1作为ASP.NET MVC3应用程序的聊天核心。使用IIS 7.5
MVC控制器中有两种方法可以访问聊天视图:
1.第一种方法是公开的,允许匿名用户聊天 - 没有授权
2.对于域用户 - 聊天代理,使用[Authorize]
属性限制访问第二种方法。
集线器中没有明确指定的授权
对于这种情况,我在IIS上涉及Windows和匿名身份验证。
我还实现了自定义角色提供程序,它只在内存中运行 - 不会将任何内容保存到数据库中。
在控制器方法中使用'[Authorize]'属性会导致来自Hub的500响应,无论是来自授权视图,还是来自匿名视图:
请求(send
是发送消息的Hub方法):
http://localhost:8101/signalr/send?transport=serverSentEvents&connectionToken=VIXEZzWQSn5SNlA8RUy4iaOPDFdvuPBjMvFBiG2FLfvfxF347XHwtapsEV5ndU4OEI0Xb64W2ZRXTqwBiL2CXg2_JlTaTJ2RnVOj4bjvx6tQaYhAqTaXs9k2853GYqzd0
响应:
The connection id is in the incorrect format.
Server stack trace:
at Microsoft.AspNet.SignalR.PersistentConnection.GetConnectionId(HostContext context, String connectionToken)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.Owin.CallHandler.Invoke(IDictionary2 environment)
at Microsoft.AspNet.SignalR.Owin.Handlers.HubDispatcherHandler.Invoke(IDictionary2 environment)
at Microsoft.Owin.Host.SystemWeb.OwinCallContext.Execute()
at Microsoft.Owin.Host.SystemWeb.OwinHttpHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object extraData)<br/><br/>
但请注意,连接到Hub工作正常,返回200 OK:
http://localhost:8101/signalr/connect?transport=serverSentEvents&connectionToken=dYOwFxa1mkgdpzw-jitRpWq9oxRlrTet8U_dAzWjFQEdGNJfVXeG7Op0NZZwvznxeNdJCuPT75CKzQqI9HRPThV3uEDt-Z2qtIl9E02gF481&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&tid=9
我在stackoverflow上发现了一些类似的线程:
signalr The connection id is in the incorrect format
据我所知,在调用我的Send
方法时,Hub处理的请求Identity
不同于用于连接到Hub的端口,OR Hub的GetConnectionId
发现,该用户实际上是没有授权 - 但是当Hub没有指定授权时,它如何检查该假设?
有人可以对此有所了解吗?
提前致谢:)
答案 0 :(得分:9)
SignalR会同时为您的连接ID和Identity
签名,以便在每次启动新连接时创建新的connectionToken
。然后,此connectionToken
作为negotiate
响应的一部分发送到SignalR客户端。
每当您向SignalR发出请求时,无论是connect
,reconnect
还是send
请求,SignalR都会验证您的connectionToken
是否与您客户的连接相匹配id AND Identity
。
connectionToken
本质上是一个CSRF令牌,用于防止运行第三方网站的攻击者秘密代表共享客户端发出SignalR请求。显然,如果你启用了SignalR的跨域支持,这没有任何帮助,但connectionToken
在这种情况下仍然有效。
Taylor's answer是正确的。当客户的stop
发生变化时,您应该start
然后Identity
建立SignalR连接。这将强制执行新的negotiate
请求,该请求会为您的客户端提供一个新的连接ID,其中新的connectionToken
已与客户更新的Identity
签名。
P.S。服务器发送的事件connect
请求未失败,因为它是在客户端Identity
更改之前建立的。仅在收到请求时检查connectionToken
,但服务器发送的事件会使响应无限期地保持打开状态。
答案 1 :(得分:3)
你所说的一切都是真的,它实际上发生在我的问题上。
但我也找到了根本原因:
设计过程中的一个主要假设是允许匿名用户在不需要登录的情况下使用聊天,并允许后端用户(代理)使用他们的Windows凭据登录到受限制的聊天区域。登记/>
因此,在IIS管理器上,我启用了匿名身份验证(允许匿名用户使用聊天)和Windows身份验证(允许代理使用其Windows凭据进行访问)。
MVC应用程序配置为使用Windows身份验证 - 提到的[Authorize]
属性,但仅限制代理的聊天视图的访问权限。
以上配置实际发生的是:
1.当客户端(代理)请求受限制的View(假设它为/Chat/Agent
)时,[Authorize]
属性初始化身份验证(Windows)
2.客户端Javascript请求Negotiate
,生成connectionId
的内容并将其与客户端的Windows Identity
绑定
3.以下是棘手的部分:由于Hub未明确使用任何身份验证,因此调用send
方法不会导致任何身份验证请求 - IIS匿名身份验证在Windows身份验证之前优先,并且send
请求随之发送匿名Identity
- 但在实际中,实际connectionId
与第2点中传递的Identity
相关。
此方案会导致您所描述的情况 - 调用connect
的{{1}}与Identity
不同,并且集线器返回send