如何基于HTTP头创建自定义身份validation机制?

我将旧版本的问题留在底部。

我想为SignalR客户端实现自定义身份validation。 在我的例子中,这是Java客户端(Android)。 不是网络浏览器。 没有表单身份validation,没有Windows身份validation。 这些是使用java库的普通vanilla客户端。

所以,假设连接到HUB的客户端传递自定义标头。 我需要以某种方式根据此标头validation用户。 这里的文档提到它是可能的,但没有提供有关如何实现它的任何细节。

这是Android方面的代码:

hubConnection = new HubConnection("http://192.168.1.116/dbg", "", true, new NullLogger()); hubConnection.getHeaders().put("SRUserId", userId); hubConnection.getHeaders().put("Authorization", userId); final HubProxy hubProxy = hubConnection.createHubProxy("SignalRHub"); hubProxy.subscribe(this); // Work with long polling connections only. Don't deal with server sockets and we // don't have WebSockets installed SignalRFuture awaitConnection = hubConnection.start(new LongPollingTransport(new NullLogger())); try { awaitConnection.get(); Log.d(LOG_TAG, "------ CONNECTED to SignalR -- " + hubConnection.getConnectionId()); } catch (Exception e) { LogData.e(LOG_TAG, e, LogData.Priority.High); } 

PS下面的原始问题是我“简化”问题的愿望。 因为我可以访问OnConnected回调中的标头。 我认为有简单的方法可以放下连接…


使用Signal R和自定义身份validation机制。 我只是检查连接客户端是否有连接请求传入的某些标头。

问题是 – 如何拒绝或不连接未通过支票的用户? 这里的文档并没有真正解释这种情况。 提到使用证书/标题 – 但没有关于如何在服务器上处理它的示例。 我不使用Forms或Windows身份validation。 我的用户 – 安卓java设备。

这是我的Hub的代码,我想拒绝连接..

 public class SignalRHub : Hub { private const string UserIdHeader = "SRUserId"; private readonly static SignalRInMemoryUserMapping Connections = new SignalRInMemoryUserMapping(); public override Task OnConnected() { if (string.IsNullOrEmpty(Context.Headers[UserIdHeader])) { // TODO: Somehow make sure SignalR DOES NOT connect this user! return Task.FromResult(0); } Connections.Add(Context.Headers[UserIdHeader], Context.ConnectionId); Debug.WriteLine("Client {0}-{1} - {2}", Context.Headers[UserIdHeader], Context.ConnectionId, "CONNECTED"); return base.OnConnected(); } 

所以我刚刚创建了一个自定义授权属性并覆盖了AuthorizeHubConnection方法以访问请求并实现了您尝试使用Header进行的逻辑,它似乎正在工作。

 using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; namespace SignalR.Web.Authorization { public class HeadersAuthAttribute : AuthorizeAttribute { private const string UserIdHeader = "SRUserId"; public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) { if (string.IsNullOrEmpty(request.Headers[UserIdHeader])) { return false; } return true; } } } 

  [HeadersAuth] [HubName("messagingHub")] public class MessagingHub : Hub { } 

这在控制台中产生了这一点(如果图片没有显示,则是[Failed to load resource: the server responded with a status of 401 (Unauthorized)]

在此处输入图像描述

事实上,接受的答案是错误的。 令人惊讶的是,授权属性应该用于授权(也就是说,您应该使用它来检查请求经过身份validation的用户是否有权执行所需的操作)。

此外,由于您使用了错误的机制,因此您没有设置HttpContext.Current.User.Identity 。 因此,您没有明确的方法将用户信息传递给您的业务/授权逻辑。

第三,这样做你将无法使用Clients.User()方法向特定用户发送消息,因为SignalR将无法在用户和连接之间进行映射。

正确的方法是插入OWIN身份validation管道。 这是一篇很好的文章 ,详细解释和演示如何实现在OWIN中使用的自定义身份validation。

我不打算在此复制粘贴,只需按照它并确保您实现所有必需的部分:

  • 选项
  • 处理器
  • 中间件

有了这些之后,将它们注册到OWIN中:

 app.Map("/signalr", map => { map.UseYourCustomAuthentication(); var hubConfiguration = new HubConfiguration { Resolver = GlobalHost.DependencyResolver, }; map.RunSignalR(hubConfiguration); });