SignalR - 使用UserID提供程序向用户发送消息

5
使用SignalR,我相信我应该能够通过使用UserID Provider向特定连接的用户发送消息。
有人有这将如何实现的示例吗?我已经搜索了很久,但找不到任何示例。我需要针对JavaScript客户端进行操作。
用例是,我的网站用户将拥有一个帐户。他们可能从多个设备/浏览器登录。当某些事件发生时,我将想要向他们发送一条消息。

那么你在某个地方跟踪Context.User.IdentityContext.ConnectionId了吗?你的用例与你提供的链接中的示例有何不同? - mrtig
不,我没有很多东西。只有一个简单的中心和连接到它的JavaScript。 - hatcyl
那么我建议您仔细查看您链接的示例。他们使用集合来维护用户名和连接,这使得他们可以在特定的连接上调用客户端方法。 - mrtig
2
嗯...也许我误解了他们的文档。在你手动同步用户ID到连接ID并适当地广播之前,我认为UserID提供程序的重点是消除这种手动跟踪。我认为它会根据普通身份验证使用的相同用户来知道用户是谁。 - hatcyl
2
关键就在于,如果你有用户名称,就不需要跟踪任何信息。默认情况下,它会使用用户名称(如果你正在使用某种验证方式来设置主体)。 - davidfowl
默认情况下,使用Clients.User(userid).nameOfYourRecievingMethod(msg)发送的任何消息都将发送到userid =传递的userid的任何客户端(即从服务器上返回的userid-任何设置)。 - MemeDeveloper
2个回答

2

我还没有研究过SignalR 2.0,但我认为它是之前版本的扩展。当你连接到hub时,可以使用Authorize属性进行装饰。

[HubName("myhub")]
[Authorize]
public class MyHub1 : Hub
{
    public override System.Threading.Tasks.Task OnConnected()
    {
        var identity = Thread.CurrentPrincipal.Identity;
        var request = Context.Request;
        Clients.Client(Context.ConnectionId).sayhello("Hello " + identity.Name);
        return base.OnConnected();
    }
}

正如您所见,您可以访问访问Hub的用户的身份标识。我认为新功能仅仅是这个的扩展。由于客户端和Hub之间的连接始终保持活动状态,因此您将始终拥有主要身份标识,该标识将向您提供用户ID。


在调试我的应用程序时,当从我的JavaScript客户端连接时,Thread.CurrentPrincipal.Identity和Context.Request都为空。是否有一种特殊的方式可以从JavaScript连接,以便它知道它需要那些信息? - hatcyl
你的 Hub 理论上应该可以使用它,没有什么理由不行。你是否已经在 global.asax 或者其他注册了 Hub 的地方添加了 GlobalHost.HubPipeline.RequireAuthentication(); 呢? - Gjohn
尚未尝试,但会尝试。不过,我应该不需要“要求”它,对吧?我应该能够同时允许授权用户和匿名用户吧? - hatcyl
谢谢,我会尝试一些建议并继续研究。我会向大家报告进展情况。 - hatcyl
我想我根据您的建议找到了解决方法。浏览器在连接时默认不发送授权标头。只有当它收到401错误时,它才会再次尝试发送授权。通过向我的Hub添加Authorized属性,浏览器被强制发送授权标头,现在我能够正确访问Context.User。 - hatcyl
显示剩余5条评论

0

我相信这可以帮助你:(从这里链接)

一个特定的用户,由userId标识。

Clients.User(userid).addContosoChatMessageToPage(name, message);

可以使用IUserId接口确定userId:
public interface IUserIdProvider
{
    string GetUserId(IRequest request);
}

IUserIdProvider 的默认实现是 PrincipalUserIdProvider。要使用此默认实现,请在应用程序启动时首先在 GlobalHost 中注册它:

var idProvider = new PrincipalUserIdProvider();
GlobalHost.DependencyResolver.Register (typeof(IUserIdProvider), () => idProvider);

通过从客户端传入请求对象,可以确定用户名。


尝试了一下,不行。还是谢谢。 - hatcyl
正如dfowler所说,没有必要这样做:“要使用此默认实现,请在应用程序启动时在GlobalHost中注册它:”,因为这是默认设置。 - MemeDeveloper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接