使用Jwt为.Net Core SignalR保驾护航
前言
SignalR Demo搭建起来之后,是没有相应的认证和授权功能的。于是乎,参考官方文档实现了相应的逻辑。
简单认证
首先使用稍微简单的方式实现。添加如下代码:
services.AddAuthentication(auth =>
{
auth.DefaultScheme = "User";
}).AddScheme<UserAuthenticationOptions, UserAuthenticationHandler>("User", o => { });
public class UserAuthenticationOptions : AuthenticationSchemeOptions
{ }
然后在新增Handler,重写 AuthenticationHandler 的HandleAuthenticateAsync 方法
public class UserAuthenticationHandler : AuthenticationHandler<UserAuthenticationOptions>
{
private readonly ILayIMUserFactory userFactory; public UserAuthenticationHandler(IOptionsMonitor<UserAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IServiceProvider serviceProvider)
: base(options, logger, encoder, clock)
{
userFactory = serviceProvider.GetService<ILayIMUserFactory>();
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
var userId = userFactory.GetUserId(Request.HttpContext);
if (string.IsNullOrEmpty(userId))
{
return Task.FromResult(AuthenticateResult.Fail("no user"));
}
var claims = new[] { new Claim("user", userId) };
var identity = new ClaimsIdentity(claims, nameof(UserAuthenticationHandler));
var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), Scheme.Name);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
}
最后在Hub上增加AuthorizeAttribute即可
[Authorize(AuthenticationSchemes = “User”)]
public class LayIMHub : Hub<ILayIMClient>{}
JWT Bearer认证
首先安装 Microsoft.AspNetCore.Authentication.JwtBearer .
然后在Startup中增加如下代码:(基本上就是官方教程中的)
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
LifetimeValidator = (before, expires, token, param) =>
{
return expires > DateTime.UtcNow;
},
ValidateAudience = false,
ValidateIssuer = false,
ValidateActor = false,
ValidateLifetime = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SignalRSecurityKey.TOKEN_KEY))
};
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("/layimHub")))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
不过AuthorizeAttribute 的Scheme 要改成 JwtBearerDefaults.AuthenticationScheme. 运行一下程序,因为刚开始没有提供token,所以肯定是401的。

对了,客户端连接的时候要加上accessTokenFactory:
var options = {};
options.accessTokenFactory = () => token;
//options.skipNegotiation = true;
connection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Trace)
.withUrl(hubRoute, options)
.withHubProtocol(protocol)
.build();
我们在实现一个获取Token的接口,在调用SignalR连接之前,先获取Token,然后把token带上即可。以下代码是生成Token的方法,Subject的内容可以随便定义
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(SignalRSecurityKey.TOKEN_KEY);
var authTime = DateTime.UtcNow;
var expiresAt = authTime.AddDays(7);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim("uid",userId)
}),
Expires = expiresAt,
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
return tokenString;
下面在看演示:

再次请求,已经带上了token头

最后,在websocket握手阶段,也会将这个token传到后端。

这样我们的程序就能正常运行了。
总结
本文只是一篇简单的流水账记录。就酱吧
使用Jwt为.Net Core SignalR保驾护航的更多相关文章
- .net core 3.0 Signalr - 05 使用jwt将用户跟signalr关联
Signalr是以Group.Connect为核心来进行推送,比如,给某个组.某个连接来推送,但实际场景中,核心应该是某个组.某个人:然而一个人可以对应多个连接(浏览器多个tab页):本节就来介绍下自 ...
- Asp.Net Core SignalR 系列博客
系列 SignalR+Vue SignalR+Vue 服务端向客户端发送信息 SignalR+Vue+Log4net 实时日志推送 待定...... 源码地址:https://github.com/Q ...
- ASP.NET Core SignalR中的流式传输
什么是流式传输? 流式传输是这一种以稳定持续流的形式传输数据的技术. 流式传输的使用场景 有些场景中,服务器返回的数据量较大,等待时间较长,客户端不得不等待服务器返回所有数据后,再进行相应的操作.这时 ...
- Asp.Net Core SignalR 用泛型Hub优雅的调用前端方法及传参
继续学习 最近一直在使用Asp.Net Core SignalR(下面成SignalR Core)为小程序提供websocket支持,前端时间也发了一个学习笔记,在使用过程中稍微看了下它的源码,不得不 ...
- Asp.Net Core SignalR 与微信小程序交互笔记
什么是Asp.Net Core SignalR Asp.Net Core SignalR 是微软开发的一套基于Asp.Net Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给 ...
- [asp.net core]SignalR一个例子
摘要 在一个后台管理的页面想实时监控一些操作的数据,想到用signalR. 一个例子 asp.net core+signalR 使用Nuget安装包:Microsoft.AspNetCore.Sign ...
- ASP.NET Core SignalR
ASP.NET Core SignalR 是微软开发的一套基于ASP.NET Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给Web客户端. 功能 自动管理连接 允许同时广播 ...
- Net Core SignalR 测试,可以用于unity、Layair、白鹭引擎、大数据分析平台等高可用消息实时通信器。
SignalR介绍 SignalR介绍来源于微软文档,不过多解释.https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?v ...
- LayIM.AspNetCore Middleware 开发日记(七)Asp.Net.Core.SignalR闪亮登场
前言 前几篇介绍了整个中间件的构成,路由,基本配置等等.基本上没有涉及到通讯部分.不过已经实现了融云的通讯功能,由于是第三方的就不在单独去写.正好.NET Core SignalR已经出来好久了, ...
随机推荐
- springboot+mybatis遇到BUG:自动注入失败
今天用springboot+mybatis写一个小demo遇到如下错误 Error starting ApplicationContext. To display the conditions rep ...
- 5 springboot 集成dubbo
Apache Dubbo 是一款高性能Java RPC框架 由阿里巴巴开源并进入Apache孵化器,官网 http://dubbo.apache.org 提供服务化基础功能: 接口远程调用,智能负载均 ...
- C#画个控件,指定字符特殊颜色显示
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- java 包装类和基础数据
package com.tercher.demo; public class LangClass { public static void main(String[] args) { //所有的包装类 ...
- Laravel之Ueditor
1.访问网址http://ueditor.baidu.com/website/download.html下载合适的编辑器版本 2.按照插件包中的index.html样式,布局页面 3.如果需要使用表单 ...
- iview动态校验表单,获取值为undefined
场景:实际代码如下:https://run.iviewui.com/XPofr3YS 原因:在动态校验名称时,没法获取值,请教了大神后,发现原来是自己demo没理清楚 这里的prop="na ...
- Git简介、安装与配置
老规矩QAQ,先来简单介绍一下Git: Git是一个分布式版本控制系统,可以理解为是一个用于管理代码,控制版本,方便多人合作开发的一款工具. Git:分布式版本控制系统. SVN.CVS:集中式版本控 ...
- Oracle 通过出生日期计算年龄
方法一: SELECT TRUNC(months_between(sysdate, birth)/12) AS age from mytable 方法二: select TRUNC((to_char( ...
- 使用ArcGIS Chef Cookbook轻松搞掂WebGIS平台部署
1.安装Chef Client v12版本. 2.复制arcgis cookbook资源到Chef安装目录. 3.考虑到一般部署的服务器环境无法连接互联网,所以需要事先部署ArcGIS Cookboo ...
- The difference between creating a string object constructor and assigning it directly
字符串对象构造方法创建和直接赋值的区别? package com.itheima_02; /* * 通过构造方法创建的字符串对象和直接赋值方式创建的字符串对象有什么区别呢? * 通过构造方法创建字符串 ...