在 .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 中心并根据应用程序的独特要求定制身份验证过程。此方法允许对令牌验证和声明提取进行细粒度控制,从而确保安全可靠的实时通信系统。

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75688.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[2018][note]用于超快偏振开关和动态光束分裂的all-optical有源THz超表——

前言 类型 太赫兹 + 超表面 太赫兹 + 超表面 太赫兹+超表面 期刊 O p e n A c c e s s Open Access Open

家里网络访问Github有时候打不开,解决办法

1、修改Hosts文件修改法 通过DNS查询工具&#xff08;如&#xff09;获取最新GitHub域名解析IP修改系统hosts文件&#xff08;路径&#xff1a;C:\Windows\System32\drivers\etc\hosts&#xff09;&#xff0c;添加&#xff1a;20.205.243.166 github.com 20.27.177.113 github…

MyBatis操作数据库(1)

1. MyBatis 简介 MyBatis 是一款持久层框架&#xff0c;简化了 JDBC 的复杂操作&#xff0c;通过配置和映射文件将 Java 对象与数据库表关联。核心优势&#xff1a; 自动管理资源&#xff1a;无需手动关闭连接、释放资源。 动态 SQL&#xff1a;支持参数绑定、条件查询等。 …

ModuleNotFoundError: No module named ‘matplotlib_inline‘

ModuleNotFoundError: No module named matplotlib_inline 1. ModuleNotFoundError: No module named matplotlib_inline2. matplotlib-inlineReferences 如果你在普通的 Python 脚本或命令行中运行代码&#xff0c;那么不需要 matplotlib_inline&#xff0c;因为普通的 Python…

SSL证书自动化管理(ACME协议)工作流程介绍

SSL证书自动化管理&#xff08;ACME协议&#xff09;是一种用于自动化管理SSL/TLS证书的协议&#xff0c;以下是其详细介绍&#xff1a; 一、ACME协议概述 ACME协议由互联网安全研究小组&#xff08;ISRG&#xff09;设计开发&#xff0c;旨在实现SSL证书获取流程的自动化。通…

基于FPGA的特定序列检测器verilog实现,包含testbench和开发板硬件测试

目录 1.课题概述 2.系统测试效果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 本课题采用基于伪码匹配相关峰检测的方式实现基于FPGA的特定序列检测器verilog实现,包含testbench和开发板硬件测试。 2.系统测试效果 仿真测试 当检测到序列的时候&#xf…

#管理Node.js的多个版本

在 Windows 11 上管理 Node.js 的多个版本&#xff0c;最方便的方法是使用 nvm-windows&#xff08;Node Version Manager for Windows&#xff09;。它允许你轻松安装、切换和管理多个 Node.js 版本。 &#x1f4cc; 方法 1&#xff1a;使用 nvm-windows&#xff08;推荐 ✅&a…

【已解决】Webstorm 每次使用 git pull/push 都要输入令牌/密码登录

解决办法&#xff1a;勾上【使用凭据帮助程序】&#xff08;英文&#xff1a;Use credential helper&#xff09;

大模型架构记录13【hr agent】

一 Function calling 函数调用 from dotenv import load_dotenv, find_dotenvload_dotenv(find_dotenv())from openai import OpenAI import jsonclient OpenAI()# Example dummy function hard coded to return the same weather # In production, this could be your back…

Spring Boot向Vue发送消息通过WebSocket实现通信

注意&#xff1a;如果后端有contextPath&#xff0c;如/app&#xff0c;那么前端访问的url就是ip:port/app/ws 后端实现步骤 添加Spring Boot WebSocket依赖配置WebSocket端点和消息代理创建控制器&#xff0c;使用SimpMessagingTemplate发送消息 前端实现步骤 安装sockjs-…

【嵌入式学习5】PyQt5模块介绍、创建第一个窗口

目录 1、PyQt介绍 ①特点 ②主要组件 2、创建第一个窗口 exce_() 1、PyQt介绍 PyQt 是一个用于创建图形用户界面&#xff08;GUI&#xff09;应用程序的 Python 库&#xff0c;它是 Qt 框架的 Python 绑定。 ①特点 跨平台&#xff1a;支持多种操作系统&#xff0c;包括…

封装自己的api签名sdk

api平台接口调用&#xff0c;需要通过签名去核对是不是有效的用户&#xff0c;&#xff0c;一般会给两个key&#xff0c;acceeKey 和 secretKey,第一个相当于用户名&#xff0c;第二个相当于密钥&#xff0c;&#xff0c;&#xff0c;前端通过一定的算法&#xff0c;&#xff0…

很简单 的 将字幕生成视频的 方法

一、一键将字幕生成视频的 方法 1、下载任性动图 10.7 以上版本 2、设置背景 1&#xff09;背景大小 拉伸背景到合适大小&#xff0c;或者选择右侧比例 2&#xff09;、直接空背景&#xff0c;设置背景颜色等详细信息 3&#xff09;、或者 复制或者突然图片做背景 3、设置文…

Spring 核心技术解析【纯干货版】- XXI:Spring 第三方工具整合模块 Spring-Context-Suppor 模块精讲

在企业级开发中&#xff0c;我们经常需要与 第三方工具 进行集成&#xff0c;如 邮件发送、任务调度、缓存管理等。Spring 为此提供了 Spring-Context-Support 模块&#xff0c;它封装了多个常见的第三方工具库&#xff0c;使得开发者可以更方便地将它们集成到 Spring 项目中。…

c++柔性数组、友元、类模版

目录 1、柔性数组&#xff1a; 2、友元函数&#xff1a; 3、静态成员 注意事项 面试题&#xff1a;c/c static的作用? C语言&#xff1a; C: 为什么可以创建出 objx 4、对象与对象之间的关系 5、类模版 1、柔性数组&#xff1a; #define _CRT_SECURE_NO_WARNINGS #…

主相机绑定小地图

资源初始化&#xff1a;在类中通过 property 装饰器定义主相机、小地图相机、小地图精灵等资源属性&#xff0c;便于在编辑器中赋值。在 start 方法里&#xff0c;当确认这些资源存在后&#xff0c;创建渲染纹理并设置其大小&#xff0c;将渲染纹理与小地图相机关联&#xff0c…

linux-core分析-柔性数组越界访问

文章目录 core的调用栈core分析修改修改原因柔性数组定义代码修改总结core的调用栈 vocb core 崩溃:core的大小都是573M左右 Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000007f789af0d0 in strlen () from /lib/libc.so.6[Current thread is 1 (LW…

leetcode 代码随想录 数组-区间和

题目 给定一个整数数组 Array&#xff0c;请计算该数组在每个指定区间内元素的总和。 输入&#xff1a; 第一行输入&#xff1a;为整数数组 Array 的长度 n&#xff0c;接下来 n 行&#xff0c;每行一个整数&#xff0c;表示数组的元素。随后的输入为需要计算总和的区间&…

部署nerdctl工具

nerdctl 是一个专为Containerd设计的容器管理命令行工具&#xff0c;旨在提供类似 Docker 的用户体验&#xff0c;同时支持 Containerd 的高级特性&#xff08;如命名空间、compose等&#xff09;。 1、下载安装 wget https://github.com/containerd/nerdctl/releases/downlo…

【论文笔记】DeepSeek-R1 技术报告

最强开源LLM&#xff0c;性能和效果都很棒&#xff1b;在数学、代码这种有标准正确答案的场景&#xff0c;表现尤为突出&#xff1b;一些其他场景的效果&#xff0c;可能不如DeepSeek-V3和Qwen。 Deepseek-R1没有使用传统的有监督微调sft方法来优化模型&#xff0c;而使用了大规…