HttpContext和SignalR HubCallerContext之间的统一静态类
我有很多依赖于HttpContext.Current的代码,我注意到来自SignalR集线器的请求有HttpContext.Current == null
,所以我的代码断了,例如:
HttpContext.Current.Request.IsAuthenticated
所以我想出了以下内容:
public static class UnifiedHttpContext { private static HubCallerContext SignalRContext { get; set; } private static int SignalRUserId { get { return WebSecurity.GetUserId(SignalRContext.User.Identity.Name); } } private static bool IsSignalRRequest { get { return SignalRContext != null; } } public static void SetSignalRContext(HubCallerContext context) { SignalRContext = context; } public static bool IsAuthenticated { get { if (!IsSignalRRequest) { return System.Web.HttpContext.Current.Request.IsAuthenticated; } else { return SignalRContext.User.Identity.IsAuthenticated; } } } public static int UserId { get { if (!IsSignalRRequest) { return WebSecurity.CurrentUserId; } else { return SignalRUserId; } } } }
在主集线器中(每个其他集线器inheritance自它):
public abstract class MainHub : Hub { public override Task OnConnected() { UnifiedHttpContext.SetSignalRContext(Context); Groups.Add(Context.ConnectionId, UnifiedHttpContext.UserId.ToString()); return base.OnConnected(); } }
-
这是正确的方法,还是已经以某种方式解决了我不知道的问题?
-
这是危险的,因为静态类在应用程序中共享,这会为所有用户设置相同的上下文吗? 如果可以,我可以按要求制作吗?
SignalR使您可以访问HubCallerContex
而不是HttpContext
。 您可以使用关键字context
来访问HubCallerContext对象。 如果要访问HttpContext
,可以从上下文中获取它,如下所示:
System.Web.HttpContextBase httpContext = Context.Request.GetHttpContext();
希望这可以帮助。
刚刚花了几个小时来解决这个问题。
看起来没有办法像使用HttpContext那样在中心类之外获取SignalR上下文:
var identity = HttpContext.Current.User.Identity;
或者在Ninject上下文中:
HttpContextBase httpContext = context.Kernel.Get(); var identity = httpContext.Current.User.Identity;
至少这个问题的答案如下: 在集线器之外获取SignalR用户(Hub.Context) 。
但在这种特殊情况下,当您需要获得当前用户身份时,有一个解决方案适用于两个领域:WebApi / MVC和SignalR。
IPrincipal principal = Thread.CurrentPrincipal; var identity = principal.Identity;
我用它在我的dependency injection代码中获取用户身份。
Morover,Context属性仅在hub方法中可用(在hub构造函数中为null)。 但Thread.CurrentPrincipal.Identity
甚至会在集线器构造函数中为您提供用户身份。