SignalR - 使用访问令牌进行身份验证

时间:2014-01-21 14:05:47

标签: signalr owin

我一直在构建一个Web服务,到目前为止,它完全由ASP.NET Web API调用组成。我现在需要将SignalR添加到混音中,但我想知道如何保持安全方面的一致性。

我目前正在使用OAuth承载令牌(使用OWIN身份验证),因此我的客户端基本上会有一个access_token,我通常会将其添加到任何Web API调用的标头中。但是,我如何使用SignalR做同样的(或类似的)?我可以在创建连接时或每次通话时进行身份验证吗?而且,最重要的是,我如何首先指定访问令牌?

感谢。

2 个答案:

答案 0 :(得分:1)

我已经编写了一个样本,帮助了一些已经使用SignalR身份验证的人。 我希望它也可以帮助你。

https://github.com/louislewis2/AngularJSAuthentication

Barguast,对不起我的回答简短。通过链接你可能会理解,有太多的动作部分让我准确地写出你应该注意的最重要部分的解释。示例代码包含三个项目,您将只关注.Api和.Web项目。

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

答案 1 :(得分:1)

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

在BackEnd中,您必须覆盖JwtBearerEvents并检查OnMessageReceived内部的access_token以及集线器端点路径

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):

public async startConnection(): Promise<void> {
    this.hubConnection = new signalR.HubConnectionBuilder()
        .withUrl('https://localhost:5001/ConnectionHub', { // ConnectionHub is hub endpoint
        accessTokenFactory: () => this.getAccessToken(),
        skipNegotiation: true,
        transport: signalR.HttpTransportType.WebSockets
    }).build();

    await this.hubConnection.start();
    // ....
}

getAccessToken(): string {
    return UserData.token !== undefined ? UserData.token : ''; // Where UserData.token is a jwt token
}

微软说: 各个中心方法也可以应用[Authorize]属性

[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();
    }