保护SignalR呼叫

时间:2012-04-03 10:01:21

标签: signalr

我正在使用SignalR Javascript客户端和ASP.NET ServiceHost。我需要SignalR集线器和回调才能被登录用户访问。我还需要能够使用HttpContext.Current.User中的FormsIdentity从Hub获取当前登录用户的身份。

  1. 如何保护集线器,以便只有经过身份验证的用户才能使用SignalR?
  2. 如何从集线器获取当前登录用户的身份?

4 个答案:

答案 0 :(得分:19)

您应该使用Hub提供的this.Context.User.IdentitySee a related question

编辑:停止未经身份验证的用户:

public void ThisMethodRequiresAuthentication()
{
  if(!this.Context.User.Identity.IsAuthenticated)
  {
    // possible send a message back to the client (and show the result to the user)
    this.Clients.SendUnauthenticatedMessage("You don't have the correct permissions for this action.");
    return;
  }

  // user is authenticated continue
}
编辑#2:编辑#2: 这可能会更好,只需返回一条消息

 public string ThisMethodRequiresAuthentication()
    {
      if(!this.Context.User.Identity.IsAuthenticated)
      {
        // possible send a message back to the client (and show the result to the user)
        return "You don't have the correct permissions for this action.");

       // EDIT: or throw the 403 exception (like in the answer from Jared Kells (+1 from me for his answer), which I actually like better than the string)
       throw new HttpException(403, "Forbidden");
      }

      // user is authenticated continue

      return "success";
    }

答案 1 :(得分:14)

您可以使用HttpApplication上的PostAuthenticateRequest事件锁定SignalR URL。将以下内容添加到Global.asax.cs

这将阻止不使用“https”或未经过身份验证的请求。

public override void Init()
{
    PostAuthenticateRequest += OnPostAuthenticateRequest; 
}

private void OnPostAuthenticateRequest(object sender, EventArgs eventArgs)
{
    if (Context.Request.Path.StartsWith("/signalr", StringComparison.OrdinalIgnoreCase))            
    {
        if(Context.Request.Url.Scheme != "https")
        {
            throw new HttpException(403, "Forbidden");
        }

        if (!Context.User.Identity.IsAuthenticated)
        {
            throw new HttpException(403, "Forbidden");
        }
    }            
}

在您的中心内,您可以通过Context对象访问当前用户。

Context.User.Identity.Name

答案 2 :(得分:4)

对于您的问题的第1部分,您可以使用如下注释(这适用于SignalR 1.1):

[Authorize]
public class MyHub : Hub
{
    public void MarkFilled(int id)
    {
        Clients.All.Filled(id);
    }
    public void MarkUnFilled(int id)
    {
        Clients.All.UnFilled(id);
    }
}

答案 3 :(得分:1)

其他答案中缺少的是能够使用SignalR的内置自定义身份验证类。关于该主题的实际SignalR文档非常糟糕,但我在页面底部留下了一条评论,详细说明了如何实际执行此操作(Authentication and Authorization for SignalR Hubs)。

基本上你覆盖了提供的SignalR AuthorizeAttribute类

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class CustomAuthAttribute : AuthorizeAttribute

然后使用类声明上方的[CustomAuth]装饰您的集线器。然后,您可以覆盖以下方法来处理身份验证:

bool AuthorizeHubConnection(HubDescriptor hubDesc, IRequest request);
bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubContext, bool appliesToMethod);

由于我在IIS服务器上并且有自定义身份验证方案,我只是从AuthorizeHubConnection方法返回true,因为在我的Auth HttpModule中我已经验证了/ signalr / connect和/ signalr / reconnect调用并保存了用户数据一个HttpContext项。因此,模块处理初始SignalR连接调用(启动Web套接字连接的标准HTTP调用)的身份验证。

要授权对特定集线器方法的调用,请根据HttpContext中保存的权限检查方法名称(它与初始连接请求中保存的HttpContext相同),并根据用户是否有权调用某个方法返回true或false

在您的情况下,您可能实际上可以使用AuthorizeHubConnection方法并使用特定角色装饰您的hub方法,因为它看起来像您正在使用标准化身份系统,但如果某些东西不能正常工作,您始终可以恢复到使用HttpModule(或OWIN)中间件进行暴力破解,并使用AuthorizeHubMethodInvocation在后续的websocket调用中查找上下文数据。

相关问题