Signalr 信令器-使用访问令牌进行身份验证

Signalr 信令器-使用访问令牌进行身份验证,signalr,owin,Signalr,Owin,到目前为止,我一直在构建一个完全由ASP.NETWebAPI调用组成的web服务。我现在需要将信号器添加到混合中,但我想知道如何保持安全方面的一致性 我目前正在使用OAuth承载令牌(带有OWIN身份验证),因此我的客户机基本上会有一个access_令牌,我通常只需将它添加到任何web API调用的头中即可。但是,如何对Signal执行相同(或类似)操作?我是在创建连接时还是在每次呼叫时进行身份验证?最重要的是,我首先应该如何指定访问令牌 谢谢。我已经编写了一个示例,它帮助了一些已经使用信号器身

到目前为止,我一直在构建一个完全由ASP.NETWebAPI调用组成的web服务。我现在需要将信号器添加到混合中,但我想知道如何保持安全方面的一致性

我目前正在使用OAuth承载令牌(带有OWIN身份验证),因此我的客户机基本上会有一个access_令牌,我通常只需将它添加到任何web API调用的头中即可。但是,如何对Signal执行相同(或类似)操作?我是在创建连接时还是在每次呼叫时进行身份验证?最重要的是,我首先应该如何指定访问令牌


谢谢。

我已经编写了一个示例,它帮助了一些已经使用信号器身份验证的人。 我希望它也能帮助你

巴古斯特,对不起,我的回答很简短。通过链接,你可能会明白,有太多的运动部件,我无法准确地写下最重要的部分,你也应该注意的解释。示例代码包含三个项目,其中您将只关注.Api和.Web项目

如果有任何部分需要进一步澄清或指导,请告诉我,我将很乐意帮助您,因为所有其他人都需要相同的示例,这就是为什么我被要求首先构建示例的原因

(这太晚了:D但可能对某人有用) 您可以将accessTokenFactory添加到客户端的hubConnection中,然后在后端(asp.net core 3.1)中进行检查

从后端,您必须覆盖JWTBeareEvents并检查OnMessageReceived内的access_令牌,以及您的集线器端点路径

services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(options =>
        {
            // other options here ... //

            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    var accessToken = context.Request.Query["access_token"];
                    var path = context.HttpContext.Request.Path;
                    if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/ConnectionHub"))) // for me my hub endpoint is ConnectionHub
                    {
                        context.Token = accessToken;
                    }
                    return Task.CompletedTask;
                }
            };
        });
从客户端添加accessToken选项(TypeScript):

最后,您可以阅读并检查hub的任何方法中的声明或身份属性:

public override async Task OnConnectedAsync()
    {
        // Get UserID. Assumed the user is logged before connecting to chat and userid is saved in session.
        string userID = Context.User.Identity.Name;

        // Get ChatHistory and call the client function. See below
        await GetHistoryAsync(userID);

        await base.OnConnectedAsync();
    }

JavaScript WebSocket API不允许设置请求头。您最好的选择是在请求url查询字符串上设置access_令牌。谢谢。我可以这样做,但是我如何配置服务器端来读取查询字符串并确定和设置集线器的标识?@Barguast您可以创建一个HubPipelineModule,为有效令牌设置用户标识,或拒绝访问无效令牌。您需要覆盖的两种方法是
OnBeforeConnect
OnBeforeIncoming
。谢谢希望在某个地方有更多关于这方面的文章?我可以看到模块如何拦截请求,以及令牌如何被解密(尽管它会很混乱),但我看不到如何在上下文中看到用户属性。我以为我要做的工作是配置OWIN而不是信号机。我想我已经取得了一些进展。我已经找到了这个问题的答案:,现在我能够在查询字符串中提供访问令牌,并从服务器上获取标识。我的WebAPI控制器现在都从授权头或查询字符串获取主体。但是,SignalR中的用户属性仍然是默认的“未验证”值!如何在OWIN配置中设置此属性的值?我认为注释(由LowQualitoPosts审阅队列自动生成)已经足够了,但请阅读SOThanks的指南。看起来您像是以与我相同的方式解决了这个问题—将访问令牌添加到查询字符串中,然后修改服务以在那里查找令牌。这对我来说一直都很好,我还没有看到任何其他的方法来做到这一点。很高兴听到你来对了。还有另一种方法,您可以将令牌放在头中,但是这条路径有一个大问题。正如你们所知,Signal支持WebSocket,对我来说这很重要。WebSocket不支持添加自定义标题,因此按照这种方式,您将不得不忘记使用WebSocket作为传输。除此之外,我没有找到其他方法。我已经按照您编写的那样设置了backend StartUp.cs,但是我不清楚如何在
getAccessToken()
方法中访问令牌,特别是
UserData
[Authorize]
public class ChatHub : Hub
{
    public async Task Send(string message)
    {
        // ... send a message to all users ...
    }

    [Authorize("Administrators")]
    public void BanUser(string userName)
    {
        // ... ban a user from the chat room (something only Administrators can do) ...
    }
}
public override async Task OnConnectedAsync()
    {
        // Get UserID. Assumed the user is logged before connecting to chat and userid is saved in session.
        string userID = Context.User.Identity.Name;

        // Get ChatHistory and call the client function. See below
        await GetHistoryAsync(userID);

        await base.OnConnectedAsync();
    }