是否可以使用HttpModule来验证SignalR

问题描述:

我正在开发一个应用程序,它使用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产品更能为您提供工作保障。

我忘了前段时间发布过这个问题。我最终在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来访问用户数据,并执行自定义逻辑以确定用户是否可以访问方法。

如果要验证每个请求以保护静态文件等,这是我可以通过验证其正常工作的最佳方式。