2012-04-03 115 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調用中查找上下文數據。