我有很多依赖于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();
}
}
这是正确的做法,还是已经以某种方式解决了我不知道的问题?
这是危险的,因为静态类在应用程序中共享,这会为所有用户设置相同的上下文吗?如果可以,我可以按要求制作吗?
答案 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
甚至会在集线器构造函数中为您提供用户身份。