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. Bugku 杂项 眼见非实

    把文件放进Kali中可以看到这是一个zip文件,解压后得到一个docx,继续翻 (在windows中是打不开的 在word/document.xml中可以找到flag

  2. 进程间通信(队列、管道)、消费者模型和进程池(apply,apply_async,map)

    一.队列(先进先出) 进程间通信:IPC(Inter-Process Communication) 队列是使用管道和锁定实现,所以Queue是多进程安全的队列,使用Queue可以实现多进程之间的数据传 ...

  3. Go语言协程

    协程的特点 1.该任务的业务代码主动要求切换,即主动让出执行权限 2.发生了IO,导致执行阻塞(使用channel让协程阻塞) 与线程本质的不同 C#.java中我们执行多个线程,是通过时间片切换来进 ...

  4. 第六十六天 js操作高级

    1.对象使用的高级 对象的key为字符类型,value为任意类型 var obj ={ name:"name", "person-age":18 } // 访问 ...

  5. mongoDB 数据库操作

    mongoDB 数据库操作 数据库命名规则 . 使用 utf8 字符,默认所有字符为 utf8 . 不能含有空格 . / \ "\0" 字符 (c++ 中会将 "\0&q ...

  6. P1742 最小圆覆盖(计算几何)

    体验过\(O(n^3)\)过\(10^5\)吗?快来体验一波当\(wys\)的快感吧\(QAQ\) 前置芝士1:二元一次方程组求解 设 \[\begin{cases}a1 * x + b1*y=c1\ ...

  7. adb调试

    adb usb调试,adb网络调试是非常实用的工具,通过电脑连接手机达到文件传输.电脑端安装app刷机等功能材料: 材料: 1.电脑端安装号对应手机的驱动程序 2.电脑端下载好adb调试工具 3.手机 ...

  8. Python生成器,迭代器,可迭代对象

    在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list,set,dict ...

  9. 老男孩Python全栈学习 S9 日常作业 007

    1.把列表中所有姓周的人的信息删掉 lst = ['周老二', '周星星', '麻花藤', '周扒皮'] lst = ['周老二', '周星星', '麻花藤', '周扒皮'] lst2 = [] fo ...

  10. 第十六节:语法总结(3)(C#6.0和C#7.0新语法)

    一. C# 6.0 新语法 1. 自动属性初始化可以赋值 /// <summary> /// 自动属性初始化 /// </summary> public class UserI ...