使用SignalR通过客户端的Windows用户名将数据发送到特定客户端

时间:2016-07-05 08:34:40

标签: c# signalr windows-authentication

我有一种类似桌面的Web应用程序,带有可拖动的项目,并且在每个项目拖放时,db都会使用新的序列化数据进行更新。现在,每当一个用户更改其布局时,他所有登录的计算机都应该实时更新。

我如何仅向具有此属性的用户发送数据:

User.Identity.Name

基本上看起来应该是这样的:

this.Clients.WithWindowsName("windowsusername").sendData(data);

1 个答案:

答案 0 :(得分:3)

首先,您需要将Windows名称发送到服务器。最快捷的方法是将其作为标题从客户端发送,因为它将包含在Start()调用中,因此您不需要额外的proxy.Invoke()

客户端

_connection = new HubConnection(_uri);
_connection.Headers.Add("windowsName", "John");
await _connection.Start();

服务器端

“windowsName”标题将是您的身份。要确保SignalR将该标头识别为标识,您需要创建IUserIdProvider

的实现
using Microsoft.AspNet.SignalR;

namespace YourServer
{
    public class UserIdProvider : IUserIdProvider
    {
        public string GetUserId(IRequest request)
        {
            return request.Headers.Get("windowsName");
        }
    }
}

然后将其插入全局依赖项解析器:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var idProvider = new UserIdProvider();
        GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);

        // TODO configure signalR here
    }
}

每当您访问User.Identity.Name时,它都会匹配“windowsName”,但您甚至不需要它,如下所述。

正如您所说,用户可以从多台计算机登录。处理此问题的最佳方法是创建SignalR组:

public override Task OnConnected()
{
    var windowsName = Context.Headers.Get("windowsName");
    Groups.Add(Context.ConnectionId, windowsName);

    return base.OnConnected();
}

这将创建一个具有Windows机器名称的SignalR组。 如果用户使用其他计算机登录,则会将其添加到同一组中。 你不需要删除OnDisconnected内的任何内容,因为SignalR会为你处理它。

组非常方便,因为无论何时向组发送消息,都会通知所有连接的计算机:

Clients.Group("John").sendData(data);
Clients.Group(User.Identity.Name).sendData(data);

即使是单个用户(从多台机器连接)也可以创建一个组。