Context.User.Identity.Name имеет значение null с SignalR 2.X.X. Как это исправить?

Это сводит меня с ума.

Я использую последнюю версию 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();
        }

И это метод входа в систему моего Контроллера:

        [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.

Вы хоть представляете, что не так?


person MRFerocius    schedule 25.02.2014    source источник
comment
Кажется, это сложный вопрос даже для ТАК ... где владельцы SignalR ... Я читал, что версия 2.0.3 может решить что-то подобное при OnDisconnected, однако никаких новостей в течение долгого времени. То, что важно для работы, например, безопасность, не работает нормально. Не повезло мне.   -  person MRFerocius    schedule 25.02.2014
comment
По какой-то причине, если часы компьютера показывают неправильное время (например, один месяц назад), Context.User будет нулевым.   -  person Tuomas Hietanen    schedule 08.02.2018


Ответы (5)


Я нашел окончательное решение, это код моего класса запуска 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 ПОСЛЕ аутентификации, и вуаля! Теперь все работает, как ожидалось.

        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();    
    }
person MRFerocius    schedule 25.02.2014
comment
Чувак, это безумие - добираться до него самостоятельно, не предоставляя никакой информации. Благодарю. в моем шаблоне это должно быть так: public void Configuration (IAppBuilder app) {ConfigureAuth (app); app.MapSignalR (); } - person Ronen Festinger; 14.10.2014
comment
@RonenFestinger Я боролся с этим, как 10 дней, без информации, когда я обнаружил, что это похоже на решение последней теоремы Фермаца. Сумасшедший: | - person MRFerocius; 14.10.2014
comment
У меня это не сработало. Я использую OwinContext и OwinContextIdentity. - person ahmadalibaloch; 21.07.2016
comment
Приготовить себе кофе - мне очень помогло) - person Timur Lemeshko; 23.09.2019

Если вы используете Web Api и SignalR в одном проекте, вам необходимо сопоставить SignalR до регистрации Web Api.

Измените это:

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

К этому:

app.MapSignalR();
app.UseWebApi(GlobalConfiguration.Configuration);
person Josh Noe    schedule 11.06.2015
comment
На этот ответ давали полтора года. - person MRFerocius; 12.06.2015
comment
@MRFerocius предоставленный вами ответ похож, но отличается. Ваш ответ - переместить app.MapSignalR() в раздел "Аутентификация". Моя - переместить его выше app.UseWebApi(). Кто-то, использующий как Web Api, так и SignalR, может найти эту информацию полезной, поскольку она не интуитивно понятна. - person Josh Noe; 12.06.2015
comment
Этот сделал это за меня! Спасибо! - person Slick86; 30.10.2015
comment
Спасибо @JoshNoe, я потратил на это слишком много времени. Это решило мою проблему. - person Jonathan; 26.08.2017

просто убедитесь, что авторизация. конфигурация вызывается перед запуском 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();


    }
}

объятия ..

person islam khateeb    schedule 31.12.2017

Если вы отображаете /signalr как «разветвленный конвейер», вам необходимо это сделать. Обязательно используйте bp.UseCookieAuthentication, а не app:

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

Совет: я произвольно изменил корпус, поэтому, когда я вижу youRaccount в строке URL-адреса, я знаю, что это сработало :-)

person Simon_Weaver    schedule 14.12.2017

Только .NET Core SignalR

Для нового .NET Core SignalR в полных инструкциях объясняется, что при использовании веб-сокетов вам необходимо вручную вытащить accessToken из строки запроса. Это легко упустить.

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

Обычно, когда вы вызываете AddAuthentication(), вам нужно добавить AddJwtBearer(), а затем установить обработчик для обработчика OnMessageReceived.

Найдите код «OnMessageReceived» в приведенной выше ссылке. Это немного коряво в том смысле, что вам даже придется добавить это самостоятельно, но именно поэтому это легко упустить.

person Simon_Weaver    schedule 06.07.2019