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

kat*_*tit 11 .net c# asp.net signalr

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

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

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

这是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<Void> 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);
        }
Run Code Online (Sandbox Code Playgroud)

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


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

问题是 - 如何拒绝或不连接未通过支票的用户?这里的文档并没有真正解释这种情况.提到使用证书/标题 - 但没有关于如何在服务器上处理它的示例.我不使用Forms或Windows身份验证.我的用户 - 安卓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();
    }
Run Code Online (Sandbox Code Playgroud)

Mar*_* C. 7

所以我只是创建了一个自定义授权属性并覆盖了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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

    }
Run Code Online (Sandbox Code Playgroud)

这在控制台中产生了这个(如果图片没有出现,那就是a [Failed to load resource: the server responded with a status of 401 (Unauthorized)]):

在此输入图像描述


Ill*_*dan 5

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

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

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

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

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

  • 选项
  • 处理程序
  • 中间件

拥有这些后,将它们注册到 OWIN:

app.Map("/signalr", map =>
{
   map.UseYourCustomAuthentication();

   var hubConfiguration = new HubConfiguration
   {
       Resolver = GlobalHost.DependencyResolver,
   };

   map.RunSignalR(hubConfiguration);
});
Run Code Online (Sandbox Code Playgroud)