在 .NET 8 中使用自定义令牌身份验证掌握 SignalR Hub 安全性

最近在练习做一个 Web 开发项目,需要使用 WebSockets 传输数据,实现实时通信。这是一个 React.js 项目,后端是 .NET。

虽然 MSDN 提供了出色的顶级文档,但它通常缺少高级用例所需的低级细节。

一种这样的场景是使用自定义令牌对 SignalR Hub 进行身份验证。是的,自定义令牌,而不是 JWT 或默认 Bearer 令牌。本文探讨如何实现这一点。最后,您将拥有一个需要身份验证并使用自定义令牌的 SignalR Hub。

自定义Token

我们将使用的自定义令牌是 Base64 编码的用户信息分隔字符串,格式如下:

userId:userName

从这个标记中,我们将提取userId并userName创建声明。

项目设置

以下是设置项目的基本步骤:

创建一个.NET项目:

dotnet new webapi

添加 SignalR 服务:

在Program.cs文件中,构建应用程序时注册 SignalR 服务:

builder.Services.AddSignalR();

创建 Hub :

创建一个名为 的目录hubs,并添加一个名为 的文件GameHub.cs。执行以下操作:

public class GameHub : Hub

{

public override Task OnConnectedAsync()

{

return base.OnConnectedAsync();

}

public override Task OnDisconnectedAsync(Exception? exception)

{

return base.OnDisconnectedAsync(exception);

}

}

映射中心:

将其GameHub作为端点公开Program.cs:

app.MapHub<GameHub>("/hubs/game");

实现自定义令牌认证

要使用自定义令牌并从中提取用户信息,我们需要一个自定义身份验证方案。在 .NET 中,身份验证方案是一个命名标识符,它指定用于对用户进行身份验证的方法或协议,例如 Cookie、JWT 持有者令牌或 Windows 身份验证。对于此场景,我们将创建一个名为的方案CustomToken。

自定义身份验证方案实现

定义自定义令牌方案选项:

public class CustomTokenSchemeOptions : AuthenticationSchemeOptions

{

public CustomTokenSchemeOptions()

{

Events = new CustomTokenEvents();

}

public new CustomTokenEvents Events

{

get => (CustomTokenEvents)base.Events!;

set => base.Events = value;

}

}

定义方案处理程序: 包含验证令牌和提取用户声明的逻辑

:CustomTokenSchemeHandler

public class CustomTokenSchemeHandler : AuthenticationHandler<CustomTokenSchemeOptions>

{

private new CustomTokenEvents Events => (CustomTokenEvents)base.Events!;

public CustomTokenSchemeHandler(

IOptionsMonitor<CustomTokenSchemeOptions> options,

ILoggerFactory logger,

UrlEncoder encoder) : base(options, logger, encoder) {}

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()

{

var messageReceivedContext = new MessageReceivedContext(Context, Scheme, Options);

await Events.MessageReceivedAsync(messageReceivedContext);

var token = messageReceivedContext.Token ?? GetTokenFromQuery();

if (token is null)

{

return AuthenticateResult.NoResult();

}

byte[] data = Convert.FromBase64String(token);

string decodedString = Encoding.UTF8.GetString(data);

string[] userInfoArray = decodedString.Split(":");

var claims = new[]

{

new Claim(ClaimTypes.Name, userInfoArray[1]),

new Claim(ClaimTypes.Sid, userInfoArray[0])

};

var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Scheme.Name));

var ticket = new AuthenticationTicket(principal, Scheme.Name);

return AuthenticateResult.Success(ticket);

}

private string? GetTokenFromQuery()

{

var accessToken = Context.Request.Query["access_token"].ToString();

return string.IsNullOrEmpty(accessToken) ? null : accessToken;

}

}

配置身份验证方案:

在以下位置注册自定义身份验证方案Program.cs:

builder.Services.AddAuthentication("CustomToken")

.AddScheme<CustomTokenSchemeOptions, CustomTokenSchemeHandler>("CustomToken", opts =>

{

opts.Events = new CustomTokenEvents

{

OnMessageReceived = context =>

{

var accessToken = context.Request.Query["access_token"];

var path = context.HttpContext.Request.Path;

if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hubs/game"))

{

context.Token = accessToken;

}

return Task.CompletedTask;

};

};

});

免责声明

本文介绍的实现灵感来自 .NET 官方存储库中的 BearerTokenScheme 源代码。我们对其进行了调整以适应此场景的自定义令牌要求。

总结

通过实施此自定义令牌身份验证方案,您可以保护 SignalR 中心并根据应用程序的独特要求定制身份验证过程。此方法允许对令牌验证和声明提取进行细粒度控制,从而确保安全可靠的实时通信系统。

欢迎随意扩展此实现,添加额外的验证、日志记录或与外部身份提供商的集成,以获得更全面的解决方案。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

相关推荐
csdn_aspnet12 天前
使用 .NET Core 7 SignalR 构建实时聊天应用程序
signalr·.net7
csdn_aspnet12 天前
.NET 9.0 SignalR 支持修剪和原生 AOT
aot·signalr·.net9
csdn_aspnet17 天前
.NetCore 8 反射与源生成器(Reflection vs Source Generators)
.net8
包达叔23 天前
Admin.Net中的消息通信SignalR解释
signalr
csdn_aspnet3 个月前
使用 SignalR 在 .NET Core 8 最小 API 中构建实时通知
signalr·.net8
Broadm3 个月前
C# - 获取枚举描述 - 使用增量源生成器
.net8·源代码生成·source generator·增量源生成器
lixww.cn5 个月前
ASP.NET Core SignalR向部分客户端发消息
javascript·websocket·vue·asp.net core·signalr
lixww.cn5 个月前
ASP.NET Core SignalR的协议协商
asp.net core·signalr
lixww.cn5 个月前
ASP.NET Core SignalR的分布式部署
redis·消息队列·asp.net core·signalr