2012-04-03 78 views
26

我使用SignalR JavaScript客户端和ASP.NET的ServiceHost。我需要SignalR集线器和回调才能被登录用户访问。我还需要能够使用从HttpContext.Current.User的FormsIdentity集线器获得当前登录身份的用户。确保SignalR呼吁

  1. 如何确保集线器的安全,以便只有经过验证的用户才能使用SignalR?
  2. 我如何在从集线器当前登录用户的身份?
+0

使用signalr 1.0和Owin锁定signalr url的另一种方法:http://eworldproblems.mbaynton.com/2012/12/securing-signalr-to-your-sites-users/ – mbaynton 2012-12-22 21:26:15

回答

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: 这可能是更好的,只是返回消息

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

好,现在任何想法如何安全的集线器,以便未经身份验证的用户无法连接? – reach4thelasers 2012-04-03 14:52:42

+0

@ reach4thelasers请参阅我的编辑。这就是我会尝试的。 – Aligned 2012-04-03 15:27:03

+0

在看了下面的@Jared Kells的答案之后,我建议如果你需要强制认证所有的方法来使用他的方法,但是如果你只需要几种方法,那么就使用我的方法。 – Aligned 2012-10-30 14:04:29

14

您可以锁定SignalR URL的使用PostAuthenticateRequest事件在你的HttpApplication上。以下添加到您的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.User.Identity.Name 
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); 
    } 
} 
0

东西从其他的答案缺少的是使用SignalR内置的定制能力auth类。在话题的实际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,因为在我的验证的HttpModule我已经authenicate的/ signalr/connect和/ signalr/reconnect调用并将用户数据保存在HttpContext项目中。因此,模块处理验证初始SignalR连接呼叫(一个标准的HTTP调用发起网络套接字连接)。

授权调用特定的集线器方法我根据保存在HttpContext中的权限(它与初始连接请求保存的是相同的HttpContext)检查方法名,并根据用户是否有权调用某个特定的方法。

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