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的。所以这里面我提供另一种解决办法:

  1. 请求时将令牌数据放到URI中,这样就可以解决webSocket请求的问题。
  2. 自定义一个 Authorize
  3. 根据票据字符串返回具体票据对象,同时判断票据是否有效。
  4. 将有效的票据存入 request.Environment["server.User"],以便于后面使用。这里的 Environment 实际就是 OWIN 的参数,而关于 OWIN 的好处可以见参考资料。
  5. 当调用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系列文章

参考资料

  1. 【Jesse Liu】ASP.NET Identity登录原理 – Claims-based认证和OWIN
  2. Authentication and Authorization for SignalR Hubs

[SignalR2] 认证和授权的更多相关文章

  1. OAuth2.0认证和授权原理

    什么是OAuth授权?   一.什么是OAuth协议 OAuth(开放授权)是一个开放标准. 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和密 ...

  2. MVC 登录认证与授权及读取登录错误码

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精    最近在自学MVC,遇到的问题很多,索性一点点总结下 ...

  3. Python+Django+SAE系列教程17-----authauth (认证与授权)系统1

    通过session,我们能够在多次浏览器请求中保持数据,接下来的部分就是用session来处理用户登录了. 当然,不能仅凭用户的一面之词,我们就相信,所以我们须要认证. 当然了,Django 也提供了 ...

  4. hOAuth2.0认证和授权原理

    原文地址: http://www.6zou.net/tech/what_is_oauth.html http://www.phpddt.com/%E4%BA%8C%E6%AC%A1%E5%BC%80% ...

  5. Open开发平台,认证,授权,计费

    1.申请appid和appkeyhttp://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0 appid:应用的唯一 ...

  6. 用户登录安全框架shiro—用户的认证和授权(一)

     ssm整合shiro框架,对用户的登录操作进行认证和授权,目的很纯粹就是为了增加系统的安全线,至少不要输在门槛上嘛. 这几天在公司独立开发一个供公司内部人员使用的小管理系统,客户不多但是登录一直都是 ...

  7. Asp.Net MVC-4-过滤器1:认证与授权

    基础 过滤器体现了MVC框架中的Aop思想,虽然这种实现并不完美但在实际的开发过程中一般也足以满足需求了. 过滤器分类 依据上篇分析的执行时机的不同可以把过滤器按照实现不同的接口分为下面五类: IAu ...

  8. ASP.NET Core 认证与授权[1]:初识认证

    在ASP.NET 4.X 中,我们最常用的是Forms认证,它既可以用于局域网环境,也可用于互联网环境,有着非常广泛的使用.但是它很难进行扩展,更无法与第三方认证集成,因此,在 ASP.NET Cor ...

  9. ASP.NET Core 认证与授权[3]:OAuth & OpenID Connect认证

    在上一章中,我们了解到,Cookie认证是一种本地认证方式,通常认证与授权都在同一个服务中,也可以使用Cookie共享的方式分开部署,但局限性较大,而如今随着微服务的流行,更加偏向于将以前的单体应用拆 ...

随机推荐

  1. Python 离线 安装requests第三方库

    一.介绍 requests是Python的一个HTTP客户端库,跟urllib,urllib2类似,不过requests的优势在于使用简单,相同一个功能,用requests实现起来代码量要少很多.毕竟 ...

  2. BZOJ4643 卡常大水题 【Tarjan】

    题目分析: 给所有边按A排序,依次加入再按B递增排序,势能分析可以发现是O(n^4)的 代码: #include<bits/stdc++.h> using namespace std; ; ...

  3. Day048--jQuery自定义动画和DOM操作

    内容回顾 BOM location.reload() 全局刷新页面 location.href location.hash location.pathname location.hostname lo ...

  4. jieba 库的使用和好玩的词云

    jieba库的使用: (1)  jieba库是一款优秀的 Python 第三方中文分词库,jieba 支持三种分词模式:精确模式.全模式和搜索引擎模式,下面是三种模式的特点. 精确模式:试图将语句最精 ...

  5. FreeNAS:创建 CIFS 匿名共享

    第一部分:数据集权限设定 浏览器访问 FreeNAS 系统的 WebGUI 管理界面,点选 “Storage” 存储图标打开存储选项卡,在卷列表中点选用于匿名共享的数据集,如有需要,也可以自行创建新的 ...

  6. 应用调试(四)系统调用SWI

    目录 应用调试(四)系统调用SWI 系统调用 SWI代码片段分析 分析sys_write 构造sys_hello 应用程序调用SWI 嵌入汇编语法 测试APP 参考 title: 应用调试(四)系统调 ...

  7. openstack项目【day23】:Neutron实现网络虚拟化

    本节内容 一 Neutron概述 二 neutron openvswitch+gre/vxlan虚拟网络 三 neutron ovs opnflow流表和l2 population 四 dhcp ag ...

  8. SpringCloud笔记三:Eureka服务注册与发现

    目录 什么是Eureka? Eureka注册的三大步 第一步,引用Maven 第二步,配置yml 第三步,开启Eureka注解 新建Eureka子项目 把provider子项目变成服务端 Eureka ...

  9. 关于MySql经典高频查询语句的整理

    一查询数值型数据: SELECT * FROM tb_name WHERE sum > 100; 查询谓词:>,=,<,<>,!=,!>,!<,=>,= ...

  10. Arduino-接口图

    Arduino开发板上数字输入输出引脚中的3.5.6.9和11都提供0V和5V之外的可变输出.在这些引脚的旁边,会标有PWM——脉冲宽度调制,PWM是英文“Pulse Width Modulation ...