使用SignalR 2.X.X,Context.User.Identity.Name为null。怎么解决?

时间:2014-02-25 00:24:35

标签: asp.net-mvc authentication signalr signalr-hub owin

这让我疯了。

我正在使用最新的signalR版本(2.0.2)。这是我的集线器代码(OnConnected)

        public override Task OnConnected()
        {
            //User is null then Identity and Name too.
            Connections.Add(Context.User.Identity.Name, Context.ConnectionId);
            return base.OnConnected();
        }

这是我的Controller的登录方法:

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
              var user = await UnitOfWork.UserRepository.FindAsync(model.UserName,  model.Password);

                if (user != null)
                {
                    await SignInAsync(user, model.RememberMe);

                    return RedirectToLocal(returnUrl);
                }
            }

            TempData["ErrorMessage"] = Resources.InvalidUserNameOrPassword;

            // If we got this far, something failed, redisplay form
            return RedirectToAction("Index","Home");
        }

我发现有些人在OnDisconnected上遇到这个问题,我甚至没有在那里。

我正在使用MCV5模板。

你知道出了什么问题吗?

6 个答案:

答案 0 :(得分:91)

我找到了最终解决方案,这是我的OWIN启动类的代码:

        public void Configuration(IAppBuilder app)
        {
        app.MapSignalR();

        // Enable the application to use a cookie to store information for the signed i user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Home/Index")
        });

        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        app.UseMicrosoftAccountAuthentication(new MicrosoftProvider().GetAuthenticationOptions());
        app.UseTwitterAuthentication(new TwitterProvider().GetAuthenticationOptions());
        app.UseFacebookAuthentication(new FacebookProvider().GetAuthenticationOptions());
        app.UseGoogleAuthentication(new GoogleProvider().GetAuthenticationOptions());    
    }

让自己喝杯咖啡,我想“在身份验证后映射SignalR怎么样,瞧! 现在它按预期工作了。 < / p>

        public void Configuration(IAppBuilder app)
        {
        // Enable the application to use a cookie to store information for the signed i user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Home/Index")
        });

        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        app.UseMicrosoftAccountAuthentication(new MicrosoftProvider().GetAuthenticationOptions());
        app.UseTwitterAuthentication(new TwitterProvider().GetAuthenticationOptions());
        app.UseFacebookAuthentication(new FacebookProvider().GetAuthenticationOptions());
        app.UseGoogleAuthentication(new GoogleProvider().GetAuthenticationOptions());

        app.MapSignalR();    
    }

答案 1 :(得分:5)

如果您在同一个项目中使用Web Api和SignalR,则必须在注册Web Api之前映射SignalR

改变这个:

app.UseWebApi(GlobalConfiguration.Configuration);
app.MapSignalR();

对此:

app.MapSignalR();
app.UseWebApi(GlobalConfiguration.Configuration);

答案 2 :(得分:2)

如果您将/signalr映射为'分支管道',则需要执行此操作。请务必使用bp.UseCookieAuthentication而不是app

app.Map("/signalr", bp =>
{
   bp.UseCookieAuthentication(new CookieAuthenticationOptions
   {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/store/youRaccount/login")
   });

提示:我总是更改了外壳,所以当我在网址栏中看到youRaccount时,我知道它有效: - )

答案 3 :(得分:2)

确保认证。配置称为启动app.MapMignalrR()

我改变了这个

 public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.MapSignalR();
        ConfigureAuth(app);



    }
}

到这个

 public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
        app.MapSignalR();


    }
}

拥抱..

答案 4 :(得分:0)

仅.NET Core SignalR

对于较新的.NET Core SignalR,完整说明解释说,使用websocket时,您需要手动从查询字符串中提取accessToken。这是  容易错过。

https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-2.2

基本上,在调用AddAuthentication()的地方,您需要添加AddJwtBearer(),然后为OnMessageReceived处理程序设置一个处理程序。

在以上链接中搜索“ OnMessageReceived”以获取代码。从某种意义上说,甚至您必须自己添加此名称,这有点过时-这就是为什么它也很容易错过的原因。

答案 5 :(得分:0)

我按照上面提到的答案做的一切都是正确的,但仍然没有解决我的问题。

以下解决方案解决了我的问题。

我使用 http 上下文 从查询参数中获取 access_token 并解码令牌,从中我能够访问所有声明。

public override Task OnConnectedAsync()
{
    var httpContext = Context.GetHttpContext();
    if (httpContext != null)
    {
        var jwtToken = httpContext.Request.Query["access_token"];
        var handler = new JwtSecurityTokenHandler();
        if (!string.IsNullOrEmpty(jwtToken))
        {
            var token = handler.ReadJwtToken(jwtToken);
            var tokenS = token as JwtSecurityToken;

           // replace email with your claim name
            var jti = tokenS.Claims.First(claim => claim.Type == "email").Value;
            if (jti != null && jti != "")
            {
                Groups.AddToGroupAsync(Context.ConnectionId, jti);
            }
        }
    }
    return base.OnConnectedAsync();
}