SignalR自身不提供任何用户认证特征,相反,是直接使用现有且基于(Claims-based)声明认证系统(关于这方面知识详见参考资料),非常明了,不解释,看代码中的验证代码:

  1. protected virtual bool UserAuthorized(IPrincipal user)
  2. {
  3. if (user == null)
  4. {
  5. return false;
  6. }
  7. if (!user.Identity.IsAuthenticated)
  8. {
  9. return false;
  10. }
  11. if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
  12. {
  13. return false;
  14. }
  15. if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
  16. {
  17. return false;
  18. }
  19. return true;
  20. }

当我们采用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。

以下是完整代码:

  1. public class QueryStringBearerAuthorizeAttribute : AuthorizeAttribute
  2. {
  3. public override bool AuthorizeHubConnection(Microsoft.AspNet.SignalR.Hubs.HubDescriptor hubDescriptor, IRequest request)
  4. {
  5. var token = request.QueryString.Get("Bearer");
  6. if (String.IsNullOrEmpty(token)) return false;
  7. var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(token);
  8. if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
  9. {
  10. // set the authenticated user principal into environment so that it can be used in the future
  11. request.Environment["server.User"] = new ClaimsPrincipal(ticket.Identity);
  12. return true;
  13. }
  14. return false;
  15. }
  16. public override bool AuthorizeHubMethodInvocation(Microsoft.AspNet.SignalR.Hubs.IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
  17. {
  18. var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId;
  19. // check the authenticated user principal from environment
  20. var environment = hubIncomingInvokerContext.Hub.Context.Request.Environment;
  21. var principal = environment["server.User"] as ClaimsPrincipal;
  22. if (principal != null && principal.Identity != null && principal.Identity.IsAuthenticated)
  23. {
  24. // create a new HubCallerContext instance with the principal generated from token
  25. // and replace the current context so that in hubs we can retrieve current user identity
  26. hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(environment), connectionId);
  27. return true;
  28. }
  29. else
  30. {
  31. return false;
  32. }
  33. }
  34. }

对于客户端我们需要将票据字符串放到一个 Bearer 里面。

  1. $.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. Netty 5 io.netty.util.IllegalReferenceCountException 异常

    异常信息 io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1 原因 handler 继承了 SimpleChan ...

  2. 进程初识和multiprocessing模块之Process

    一.什么是进程 进程就是运行中的程序 进程是操作系统中最小的资源分配单位 进程与进程之间的关系 : 数据隔离的 进程的id:Process id = pid pid是一个全系统唯一的对某个进程的标识, ...

  3. MongoDB和pymongo的CURD

    一.mongodb 1.介绍 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之 ...

  4. Magento 架构原则

    Magento架构原则 >OOP体系结构和编程原则OOP体系结构和编程原则面向对象编程(OOP)设计允许软件组件具有最大的灵活性和可扩展性,允许您设计和实现高度定制的网站.面向对象原则的优点包括 ...

  5. 【并发编程】【JDK源码】CAS与synchronized

    线程安全 众所周知,Java是多线程的.但是,Java对多线程的支持其实是一把双刃剑.一旦涉及到多个线程操作共享资源的情况时,处理不好就可能产生线程安全问题.线程安全性可能是非常复杂的,在没有充足的同 ...

  6. Markdown初入门(使用Typora编辑)

    标题 使用#来实现标题的大小控制 # h1 标题1 ## h2 标题2 ### h3 标题3 #### h4 标题4 ##### h5 标题5 ###### h6 标题6 标题一 标题二 标题三 标题 ...

  7. Qt: 非阻塞时间延迟;

    1.使用时间耗损循环: #include <QTime> ... QTime delayTime = QTime::currentTime().addMSecs(1000); while( ...

  8. Node.js模块化教程

    Node.js模块化教程 下载安装node.js 创建项目结构 |-modules |-module1.js |-module2.js |-module3.js|-app.js|-package.js ...

  9. saltstack主机管理项目:今日总结(六)

    一.总目录 二.具体代码 salt #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:luoahong import os,sys if __ ...

  10. Entity Framework入门教程(14)---DbFirst下的存储过程

    EF6中DbFirst模式下使用存储过程 我们已经知道EF可以将L2E或Entity SQL的查询语句自动转换成SQL命令,也可以根据实体的状态自动生成Insert/update/delete的Sql ...