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. ueditor 插件集成到 xadmin 中的相关操作

    安装 点击这里下载源码包 在相关的虚拟环境下安装源码方式安装 切入解压后路径进行 python setup.py install 注册 安装成功按照普通app一般注册在 django 程序的app 中 ...

  2. Git让你从入门到精通,看这一篇就够了

    简介 Git 是什么? Git 是一个开源的分布式版本控制系统. 什么是版本控制? 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统. 什么是分布式版本控制系统? 介绍分布 ...

  3. 「洛谷3469」「POI2008」BLO-Blockade【Tarjan求割点】

    题目链接 [洛谷传送门] 题解 很显然,当这个点不是割点的时候,答案是\(2*(n-1)\) 如果这个点是割点,那么答案就是两两被分开的联通分量之间求组合数. 代码 #include <bits ...

  4. Mysql注入小tips --持续更新中

    学习Web安全好几年了,接触最多的是Sql注入,一直最不熟悉的也是Sql注入.OWASP中,Sql注入危害绝对是Top1.花了一点时间研究了下Mysql类型的注入. 文章中的tips将会持续更新,先说 ...

  5. LOJ#2339 通道

    题意:给你三棵树,求所有点对在三棵树上的距离和中的最大值. 解:首先有个暴力,然后还有个迭代乱搞,可以得到61分... namespace bf { inline void solve() { ; i ...

  6. POJ - 3616 Milking Time (动态规划)

    Bessie is such a hard-working cow. In fact, she is so focused on maximizing her productivity that sh ...

  7. 二.django项目环境搭建

    Ⅰ.web框架介绍 1.socket 服务端 1)客户端(手机中各种app.浏览器)是用来与服务端(网站的服务器程序)进行交互的 2)服务端类似发电厂,客户端类似电器,socket类似插座,互联网的数 ...

  8. end to end testing

    概念 https://www.softwaretestinghelp.com/what-is-end-to-end-testing/ What is “End to End Testing”? Ter ...

  9. iTOP-4418开发板和6818开发板-第五路串口介绍

    iTOP-4418开发板和6818开发板 的除去默认 4 个串口的配置和用法. 4418 的开发板最多支持 5 路串口,如下图所示,4418 的 datasheet.   6818 的开发板最多支持 ...

  10. Linux Socket I/O

    Ref: 一文读懂Socket通信原理 幽默讲解 Linux 的 Socket IO 模型