SignalR自身不提供任何用户认证特征,相反,是直接使用现有且基于(Claims-based)声明认证系统(关于这方面知识详见参考资料),非常明了,不解释,看代码中的验证代码:
protected virtual bool UserAuthorized(IPrincipal user)
{
if (user == null)
{
return false;
}
if (!user.Identity.IsAuthenticated)
{
return false;
}
if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
{
return false;
}
if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
{
return false;
}
return true;
}
当我们采用ASP.NET认证系统时,会自动处理认证信息,所以我们只需要关心我们的授权部分。
Authorize
属性
[Authorize]
属性来指定哪里用户可以访问Hub或Hub下的某个方法,这种办法如同ASP.NET MVC完全一样,它包括三个属性:
[Authorize]
只允许授权用户访问。[Authorize(Roles = "Admin,Manager")]
指定拥有 Admin、Manager 角色。[Authorize(Users = "user1,user2")]
指定用户名为 user1、user2 访问。[Authorize(RequireOutgoing=false)]
当设置为false后可以限定某些人在服务端中调用,但所有人都可以接收消息。
当然我们也可以直接在 Startup.cs
调用 GlobalHost.HubPipeline.RequireAuthentication();
,这相当于所有Hub都需要用户认证。
自定义 Authorize
可以直接继承 AuthorizeAttribute
类,其中我们可以重写 UserAuthorized
来调整我们的授权逻辑。
其实整个SignalR的认证就是调用ASP.NET的认证体系,SignalR只是重写的授权这一部分,但授权也非常简单无非就是是否验证成功、角色授权等等。
以下我会提几下特殊的情况:
杜绝 Session
很多项目都会使用Session来保存用户认证信息,但确保不要这么做,在SignalR官网默认也是建议不使用Session,当然你可以使用它,但你启用后他会打破双向通信,也就是说你将无法体验双向通信功能。具体原因我未证实但应该是由于Session会导致每一次请求数据进行一次序列化这完全不符合双向通信的原则嘛。
ASP.NET API中的OAuth2票据令牌认证
这个比较特殊是在于对于默认发送票据字符串是靠header,而对于webSocket是不允许添加header的。所以这里面我提供另一种解决办法:
- 请求时将令牌数据放到URI中,这样就可以解决webSocket请求的问题。
- 自定义一个
Authorize
。 - 根据票据字符串返回具体票据对象,同时判断票据是否有效。
- 将有效的票据存入
request.Environment["server.User"]
,以便于后面使用。这里的Environment
实际就是 OWIN 的参数,而关于 OWIN 的好处可以见参考资料。 - 当调用Hub方法时,我们重新构建一个
HubCallerContext
,当然是先将票据对象写入才重新构建的,这样子我们的上下文是一个带有 Context.User。
以下是完整代码:
public class QueryStringBearerAuthorizeAttribute : AuthorizeAttribute
{
public override bool AuthorizeHubConnection(Microsoft.AspNet.SignalR.Hubs.HubDescriptor hubDescriptor, IRequest request)
{
var token = request.QueryString.Get("Bearer");
if (String.IsNullOrEmpty(token)) return false;
var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(token);
if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
{
// set the authenticated user principal into environment so that it can be used in the future
request.Environment["server.User"] = new ClaimsPrincipal(ticket.Identity);
return true;
}
return false;
}
public override bool AuthorizeHubMethodInvocation(Microsoft.AspNet.SignalR.Hubs.IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
{
var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId;
// check the authenticated user principal from environment
var environment = hubIncomingInvokerContext.Hub.Context.Request.Environment;
var principal = environment["server.User"] as ClaimsPrincipal;
if (principal != null && principal.Identity != null && principal.Identity.IsAuthenticated)
{
// create a new HubCallerContext instance with the principal generated from token
// and replace the current context so that in hubs we can retrieve current user identity
hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(environment), connectionId);
return true;
}
else
{
return false;
}
}
}
对于客户端我们需要将票据字符串放到一个 Bearer
里面。
$.connection.hub.start({ qs: { Bearer: 'xxxxxx' } });
总结
SignalR的认证和ASP.NET完全是一起的,所以关于这一点完全没有任何学习成本。但最好采用claims-based identity认证方式,同时杜绝在SignalR里面使用Session。
查看 SignalR系列文章
参考资料
本博客Android APP 下载 |
![]() |
支持我们就给我们点打赏 |
![]() |
支付宝打赏 支付宝扫一扫二维码 |
![]() |
微信打赏 微信扫一扫二维码 |
![]() |
如果想下次快速找到我,记得点下面的关注哦!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2016-08-28 video.js--很赞的H5视频播放库
2016-08-28 后台管理UI皮肤的选择
2016-08-28 【总结】详细说说@Html.ActionLink()的用法
2016-08-28 WeX5开源免费跨端开发工具-html5 app开发就用WeX5
2016-08-28 我是怎么找电子书的?
2016-08-28 下载本 WebEnh博客 安卓APP