HttpContext和SignalR HubCallerContext之间的统一静态类

时间:2014-02-09 13:45:47

标签: c# asp.net-mvc signalr httpcontext

我有很多依赖于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;
               }
            }
        }
    }

在主集线器中(每个其他集线器继承自它):

public abstract class MainHub : Hub
{
        public override Task OnConnected()
        {
            UnifiedHttpContext.SetSignalRContext(Context);
            Groups.Add(Context.ConnectionId, UnifiedHttpContext.UserId.ToString());
            return base.OnConnected();
        }
}
  • 这是正确的做法,还是已经以某种方式解决了我不知道的问题?

  • 这是危险的,因为静态类在应用程序中共享,这会为所有用户设置相同的上下文吗?如果可以,我可以按要求制作吗?

2 个答案:

答案 0 :(得分:16)

SignalR可让您访问HubCallerContex而不是HttpContext。您可以使用关键字context访问HubCallerContext对象。如果您想访问HttpContext,可以按如下方式从上下文中获取它:

System.Web.HttpContextBase httpContext = Context.Request.GetHttpContext();

希望这有帮助。

答案 1 :(得分:4)

花了几个小时来解决这个问题。

看起来没有办法像使用HttpContext那样在中心类之外获取SignalR上下文:

var identity = HttpContext.Current.User.Identity;

或在Ninject上下文中:

HttpContextBase httpContext = context.Kernel.Get<HttpContextBase>();
var identity = httpContext.Current.User.Identity;

至少这个问题的答案如下:Get SignalR User (Hub.Context) outside of hub

但是在这种特殊情况下,当您需要获得当前用户身份时,有一个解决方案适用于两个领域:WebApi / MVC和SignalR。

IPrincipal principal = Thread.CurrentPrincipal;
var identity = principal.Identity;

我用它在我的依赖注入代码中获取用户身份。

Morover,Context属性仅在hub方法中可用(在hub构造函数中为null)。但Thread.CurrentPrincipal.Identity甚至会在集线器构造函数中为您提供用户身份。