在从Web访问的自托管SignalR服务器中实现授权

时间:2013-04-05 21:24:45

标签: signalr signalr-hub signalr.client

我正在寻找关于如何在自托管(非IIS)环境中运行的后端服务上实现SignalR的授权安全性的一些指导,该环境是从Web应用程序调用的。后端应用程序基本上是一个监视器,可以将SignalR事件激发回基于HTML的客户端。这一切都很好(实际上非​​常好)。

但是,我们需要从网站限制对经过身份验证的用户的服务器访问。所以基本上如果用户在网站上进行了身份验证,我们需要在后端应用程序中以某种方式获取凭据(用户名已足够)和验证状态,以决定是否允许连接以避免未经授权的访问。

任何人都可以指出如何完成这种授权转发的某些策略或模式吗?

2 个答案:

答案 0 :(得分:3)

我在这里遇到类似的问题,因为在我的网络应用程序中,我使用一个简单的cookie身份验证系统,该系统使用AoP样式方法检查具有属性的任何控制器,然后将获取当前上下文(来自静态HttpContext) .Current或来自目标调用对象,具体取决于拦截器的类型)然后验证cookie是否存在,它包含正确的数据,然后最终用db或cache等验证令牌。

无论如何,这种方法也可以用于Signalr,虽然它有点啰嗦,你正在使用依赖注入。你基本上用所需的属性包装集线器调用,然后设置你的DI / IoC配置来拦截这些调用,然后在你的拦截器中获取集线器实例并从请求中获取cookie(或你的自定义身份验证机制),验证它是全部有效还是没有,如果没有,那么抛出一个new HttpException("403", "Not authenticated"); 应该踢出用户并在它甚至到达你的集线器方法之前返回,这样你就可以把逻辑放入一个地方(您的拦截器,或拦截器消耗的类)然后只需使用您的属性包装任何需要使用此身份验证的方法。

我使用Ninject和拦截扩展,但是现在大多数主要的DI框架都有某种形式的IoC插件/扩展,例如Autofac,Windsor,Spring等。

如果您不喜欢将DI和/或AOP引入当前项目的路线,那么也许您可以创建一个包含您的身份验证逻辑的自定义中心实例,然后只需在您的集线器中使用它,这样就可以了您仍然会在每个要保护的集线器方法中手动调用某些身份验证逻辑,但代码较少,如下所示:

public class AuthorisableHub : Hub
{
    private ISomeAuthenticationToken GetSomeAuthenticationTokenFromRequest(Request request) // probably a SignalR specific request object
    {
        // Get your token from the querystring or cookie etc
    }

    private bool IsAuthenticationTokenValid(ISomeAuthenticationToken token)
    {
        // Perform some validation, be it simple or db based and return result
    }

    protected void PerformUserAuthentication()
    {
        var token = GetSomeAuthenticationTokenFromRequest(Context.Request);
        var isRequestValid = IsAuthenticationTokenValid(token);

        if(!isRequestValid)
        { throw new HttpException(403, "<Some forbidden message here>"); }
    }
}

public class MyFancyPantsHub : AuthorisableHub
{
    public void TellAllClientsSomethingSecret(ISecret secret)
    {
        PerformUserAuthentication();

        // Do stuff with the secret as it should have bombed the user out
        // before it reaches here if working correctly
    }
}

它不完美但会起作用(我想),我也确定我曾经读过某个地方为每个请求重新实例化了Hub,如果确实如此,你可能只是把这个逻辑放在你的构造函数中您希望将身份验证应用于集线器中的每个操作。

希望有所帮助,或者给你一些想法......最终会知道你是如何解决它的。

答案 1 :(得分:2)

SignalR不提供任何其他身份验证功能。相反,它旨在与您的应用程序的身份验证机制一起使用。

<强>集线器

您应该像往常一样进行身份验证,然后使用SignalR提供的Authorize属性来强制执行集线器上的身份验证结果。

Authorize属性可以应用于整个Hub或Hub中的特定方法。一些例子:

  • [授权] - 仅经过身份验证的用户
  • [授权(角色=“管理员,经理”)] - 仅指定.NET角色中经过身份验证的用户
  • [授权(Users =“user1,user2”)] - 仅具有指定用户名的经过身份验证的用户

您还可以通过在Application_Start方法中添加以下方法来要求所有集线器都要求身份验证:

  

GlobalHost.HubPipeline.RequireAuthentication();

持久连接

您可以在请求中使用用户对象来查看用户是否已通过身份验证:

  

request.User.IsAuthenticated