2017-05-31 32 views
3

我正在開發一個應用程序,它使用HttpModule來執行自定義驗證和授權。我的問題是在SignalR上下文對象中無法訪問在HttpModule中設置的用戶標識。是否可以使用HttpModule來驗證SignalR

我做了以下我的HttpModule後自定義驗證邏輯的BeginRequest處理程序:

var userClaims = new List<Claim>(); 
userClaims.Add(new Claim(ClaimTypes.NameIdentifier, <some id>)); 
userClaims.Add(new Claim(ClaimTypes.Name, <some name>)); 
userClaims.Add(new Claim(ClaimTypes.Email, <da email>)); 
userClaims.Add(new Claim(ClaimTypes.Authentication, "true")); 

var id = new ClaimsIdentity(userClaims); 
var principal = new ClaimsPrincipal(new[] { id }); 
Thread.CurrentPrincipal = principal; 
HttpContext.Current.User = principal; 

我認爲這絕對會做一切以下行爲就像請求被驗證,但是這種情況並非如此。

我創建了一個SignalR AuthorizeAttribute類來處理,看起來像這樣的認證:

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] 
public class CustomAuthAttribute : AuthorizeAttribute 
{ 
    public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) 
    { 
     if (HttpContext.Current.Request.Path.StartsWith("/signalr/connect")) 
     { 
      var test = (ClaimsPrincipal)HttpContext.Current.User; 
      var test2 = (ClaimsPrincipal)Thread.Current.Principal; 
     } 

     return true; 
    } 

    public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubContext, bool appliesToMethod) 
    { 
     var test = (ClaimsPrincipal)hubContext.Hub.Context.User; 
     return true; 
    } 
} 

所以我的計劃是從AuthorizeHubMethodInvocation方法中訪問hubContext.Hub.Context.User VAR做任何我需要自定義授權。但是,它只包含默認的WindowsPrincipal。

如果我查看AuthorizeHubConnection調用(實際上它是一個常規的HTTP請求而不是websocket調用),我看到HttpContext.Current對象也沒有用戶設置,因爲它應該。

我確實看到我可以訪問HttpContext.Current.Items集合。我猜想我可以用這個將信號從模塊拋到SignalR上下文中,但我不確定這是我應該做的。

最好是簡單地將HttpModule重寫爲OWIN中間件?無論如何,如果我們更新到ASP.NET 5,看起來我不得不改變東西;沒有什麼比MS產品更能爲您提供工作保障。

回答

2

我忘了前段時間發佈過這個問題。我最終在MS文章Authentication and Authorization for SignalR Hubs的評論中解釋了我的解決方案。在嘗試實現用於auth的OWIN中間件之後,我發現我將不得不做一些愚蠢的配置來爲所有請求運行所有模塊,這是低效的。我無法弄清楚如何爲所有請求運行Auth OWIN中間件組件,所以我放棄了這種方法並堅持使用我的HttpModule。這裏是我的SignalR身份驗證解決方案的摘要的鏈接頁面上公佈:

1)創建一個AuthorizeAttribute類之類的文章中指出:)

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

2與權威性類裝飾你的集線器類你創建。命名規則似乎是auth類本身的(SomeName)屬性,以及集線器裝飾的(SomeName)。

[CustomAuth] 
public class ServerWebSocket : Hub 

3)除了重寫「UserAuthorized」方法,如在文檔中,重寫以下方法(我得到這個從其他SO崗位,但現在我不能找到它):

public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) 
public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubContext, bool appliesToMethod) 

爲了實際授權我趕上SignalR的連接請求的用戶在我的HttpModule,並在HttpContext的Items集合設置的項目,像這樣:

if (req.Path.StartsWith("/signalr/connect") || req.Path.StartsWith("/signalr/reconnect")) 
{ 
    var user_info = doFullAuth(<some token>); 
    HttpContext.Current.Items.Add("userDat", user_info); 
} 

這實際上是設置了這麼塔如果用戶沒有權限,t連接請求將在HttpModule中被完全拒絕。所以我實際上並沒有實施SignalR auth方法「AuthorizeHubConnection」。但在「AuthorizeHubMethodInvocation」方法中,我通過調用原始連接請求上設置的HttpContext.Current.Items來訪問用戶數據,並執行自定義邏輯以確定用戶是否可以訪問方法。

如果要驗證每個請求以保護靜態文件等,這是我可以通過驗證其正常工作的最佳方式。

相關問題