ASP.NET_SessionId + OWIN Cookies не отправляются в браузер


145

У меня странная проблема с использованием аутентификации файла cookie Оуэна.

Когда я запускаю свой сервер IIS, аутентификация отлично работает в IE / Firefox и Chrome.

Я начал проводить тестирование с аутентификацией и входом в систему на разных платформах, и у меня возникла странная ошибка. Спорадически среда Owin / IIS просто не отправляет куки в браузеры. Я введу имя пользователя и пароль, которые верны, код запускается, но в браузер не доставляются файлы cookie. Если я перезагружаю сервер, он начинает работать, и в какой-то момент я попытаюсь войти в систему, и снова куки перестают доставляться. Переход по коду ничего не делает и не выдает ошибок.

 app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationMode = AuthenticationMode.Active,
            CookieHttpOnly = true,
            AuthenticationType = "ABC",
            LoginPath = new PathString("/Account/Login"),
            CookiePath = "/",
            CookieName = "ABC",
            Provider = new CookieAuthenticationProvider
               {
                  OnApplyRedirect = ctx =>
                  {
                     if (!IsAjaxRequest(ctx.Request))
                     {
                        ctx.Response.Redirect(ctx.RedirectUri);
                     }
                 }
               }
        });

И в моей процедуре входа в систему у меня есть следующий код:

IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
                            authenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);

var authentication = HttpContext.Current.GetOwinContext().Authentication;
var identity = new ClaimsIdentity("ABC");
identity.AddClaim(new Claim(ClaimTypes.Name, user.Username));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.User_ID.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Role, role.myRole.ToString()));
    authentication.AuthenticationResponseGrant =
        new AuthenticationResponseGrant(identity, new AuthenticationProperties()
                                                   {
                                                       IsPersistent = isPersistent
                                                   });

authenticationManager.SignIn(new AuthenticationProperties() {IsPersistent = isPersistent}, identity);

Обновление 1. Кажется, что одной из причин проблемы является то, что когда я добавляю элементы в сеанс, начинаются проблемы. Session.Content["ABC"]= 123Кажется, добавление чего-то простого создает проблему.

Что я могу разглядеть, так это: 1) (Chrome) При входе в систему я получаю ASP.NET_SessionId + мой файл cookie аутентификации. 2) Я захожу на страницу, которая устанавливает session.contents ... 3) Откройте новый браузер (Firefox) и попробуйте войти в систему, и он не получит ASP.NET_SessionId и не получит Cookie проверки подлинности 4) Пока первый браузер имеет ASP.NET_SessionId, он продолжает работать. В тот момент, когда я удаляю этот файл cookie, возникает та же проблема, что и во всех других браузерах, с которыми я работаю по IP-адресу (10.xxx) и localhost.

Обновление 2:ASPNET_SessionId принудительное создание первого на моей странице login_load перед аутентификацией с помощью OWIN.

1) перед тем, как пройти аутентификацию с помощью OWIN, я делаю случайное Session.Contentзначение на странице входа в систему, чтобы запустить ASP.NET_SessionId. 2) Затем я аутентифицируюсь и выполняю дальнейшие сеансы. 3) Кажется, теперь работают другие браузеры.

Это странно. Я могу только заключить, что это как-то связано с ASP и OWIN, думая, что они находятся в разных доменах или что-то в этом роде.

Обновление 3 - Странное поведение между ними.

Выявлено дополнительное странное поведение - Таймаут Оуэна и ASP-сессии различны. Что я вижу, так это то, что мои сеансы Owin остаются живыми дольше, чем мои сеансы ASP через некоторый механизм. Поэтому при входе в систему: 1.) У меня есть сеанс аутентификации, основанный на кулинарии 2.) Я установил несколько переменных сеанса

Мои переменные сеанса (2) «умирают» до того, как переменная сеанса cookie-файла owin вызывает повторный вход в систему, что вызывает неожиданное поведение во всем приложении. (Человек вошел в систему, но на самом деле не вошел в систему)

Обновление 3B

После некоторых копаний я увидел на странице несколько комментариев, в которых говорится, что время аутентификации «форм» и время сеанса должны совпадать. Я думаю, что обычно они синхронизированы, но по какой-то причине они не синхронизированы.

Резюме обходных путей

1) Всегда создавайте сеанс перед аутентификацией. В основном создать сеанс при запуске приложенияSession["Workaround"] = 0;

2) [Экспериментально], если вы сохраняете куки, убедитесь, что ваш тайм-аут / длина OWIN больше, чем ваш sessionTimeout в вашем web.config (в тестировании)


1
Может подтвердить, что добавление сеансового вызова в ActionResult Login и ActionResult ExternalLogin устранило эту проблему. Я уверен, что нужен только один, но у меня есть оба на месте.
— Скотт

Спасибо! ... Добавление сессии в ExternalLogin исправило это для меня ... это магия вуду ... я уже потратил 6 часов на
— поиски

Ответы:


159

Я столкнулся с той же проблемой и проследил причину реализации хостинга OWIN ASP.NET. Я бы сказал, что это ошибка.

Некоторый фон

Мои выводы основаны на следующих версиях сборки:

  • Microsoft.Owin, версия = 2.0.2.0, культура = нейтральная, PublicKeyToken = 31bf3856ad364e35
  • Microsoft.Owin.Host.SystemWeb, версия = 2.0.2.0, культура = нейтральная, PublicKeyToken = 31bf3856ad364e35
  • System.Web, версия = 4.0.0.0, культура = нейтральная, PublicKeyToken = b03f5f7f11d50a3a

OWIN использует собственную абстракцию для работы с ответными файлами cookie ( Microsoft.Owin.ResponseCookieCollection ). Эта реализация напрямую переносит коллекцию заголовков ответов и соответственно обновляет заголовок Set-Cookie . OWIN ASP.NET host ( Microsoft.Owin.Host.SystemWeb ) просто оборачивает System.Web.HttpResponse и его коллекцию заголовков. Поэтому, когда новый файл cookie создается через OWIN, ответный заголовок Set-Cookie изменяется напрямую.

Но ASP.NET также использует свою собственную абстракцию для работы с куки-файлами ответа. Это представлено нам как свойство System.Web.HttpResponse.Cookies и реализовано закрытым классом System.Web.HttpCookieCollection . Эта реализация не переносит ответ Set-Cookie заголовок напрямую, но использует некоторые оптимизации и несколько внутренних уведомлений, чтобы продемонстрировать, что его измененное состояние передано объекту ответа.

Затем в конце срока действия запроса наступает момент, когда проверяется измененное состояние HttpCookieCollection ( System.Web.HttpResponse.GenerateResponseHeadersForCookies () ), и файлы cookie сериализуются в заголовок Set-Cookie . Если эта коллекция находится в каком-то определенном состоянии, весь заголовок Set-Cookie сначала очищается и воссоздается из файлов cookie, хранящихся в коллекции.

Реализация сеанса ASP.NET использует свойство System.Web.HttpResponse.Cookies для хранения файла cookie ASP.NET_SessionId. Также есть некоторая базовая оптимизация в модуле состояния сеанса ASP.NET ( System.Web.SessionState.SessionStateModule ), реализованная с помощью статического свойства s_sessionEverSet, которое само собой разумеется. Если вы когда-нибудь сохраните что-либо для состояния сеанса в своем приложении, этот модуль будет выполнять немного больше работы для каждого запроса.


Вернуться к нашей проблеме входа

Со всеми этими частями ваши сценарии могут быть объяснены.

Случай 1 - Сессия никогда не была установлена

Свойство System.Web.SessionState.SessionStateModule , s_sessionEverSet имеет значение false. Модуль состояния сеанса не генерирует идентификаторы сеанса, и состояние коллекции System.Web.HttpResponse.Cookies не определяется как измененное . В этом случае OWIN куки отправляются в браузер корректно и логин работает.

Случай 2 - Сессия использовалась где-то в приложении, но не раньше, чем пользователь пытается аутентифицироваться

System.Web.SessionState.SessionStateModule , свойство s_sessionEverSet имеет значение true. Id сеанса генерируется SessionStateModule , ASP.NET_SessionId добавляется System.Web.HttpResponse.Cookies коллекции , но он удален позже в жизни запроса , поскольку сеанс пользователя фактически пуст. В этом случае состояние коллекции System.Web.HttpResponse.Cookies определяется как измененное, и заголовок Set-Cookie сначала очищается перед сериализацией файлов cookie в значение заголовка.

В этом случае куки-файлы ответа OWIN «теряются», и пользователь не проходит проверку подлинности и перенаправляется обратно на страницу входа.

Случай 3 - Сеанс используется до того, как пользователь пытается аутентифицироваться

System.Web.SessionState.SessionStateModule , свойство s_sessionEverSet имеет значение true. Id сеанса генерируются SessionStateModule , ASP.NET_SessionId добавляется System.Web.HttpResponse.Cookies . Из-за внутренней оптимизации в System.Web.HttpCookieCollection и System.Web.HttpResponse.GenerateResponseHeadersForCookies () заголовок Set-Cookie НЕ сначала очищается, а только обновляется.

В этом случае в ответ отправляются как файлы cookie аутентификации OWIN, так и файл cookie ASP.NET_SessionId, и вход в систему работает.


Более общая проблема с куки

Как видите, проблема носит более общий характер и не ограничивается сессией ASP.NET. Если вы размещаете OWIN через Microsoft.Owin.Host.SystemWeb и вы / что-то напрямую используете коллекцию System.Web.HttpResponse.Cookies, вы рискуете.

Например, это работает, и оба куки правильно отправляются в браузер ...

public ActionResult Index()
{
    HttpContext.GetOwinContext()
        .Response.Cookies.Append("OwinCookie", "SomeValue");
    HttpContext.Response.Cookies["ASPCookie"].Value = "SomeValue";

    return View();
}

Но это не так, и OwinCookie "потерян" ...

public ActionResult Index()
{
    HttpContext.GetOwinContext()
        .Response.Cookies.Append("OwinCookie", "SomeValue");
    HttpContext.Response.Cookies["ASPCookie"].Value = "SomeValue";
    HttpContext.Response.Cookies.Remove("ASPCookie");

    return View();
}

Оба протестированы из VS2013, IISExpress и шаблон проекта MVC по умолчанию.


7
Я провел несколько дней, пытаясь отладить и решить эту проблему в нашей тестовой среде. Единственный обходной путь, который я нашел, такой же, как вы предлагали (настройка сеанса до аутентификации пользователя). Я сообщил об этой проблеме в katanaproject ... katanaproject.codeplex.com/workitem/197 , так что, возможно, кто-то там прокомментирует.
— Томас Долезал

11
Это довольно серьезный недостаток, тем более что они упакованы в шаблон для vs2013.
— Петр Стулинский

2
Для тех, кто хочет исследовать это дальше, я создал тестовый проект на github.com/Neilski/IdentityBugDemo
— Neilski

1
Эта проблема возникает из-за использования Controller.TempData, который использует Session в качестве резервного хранилища. Может легко воспроизвести невозможность входа в систему, если файл cookie ASP_NET.SessionId не существует из предыдущего запроса.
— кингданго

2
В заключение! Что за странная проблема? Спасибо. Это все еще проблема в течение двух лет после написания этого ответа.
— Spivonious

43

Начав с большого анализа @TomasDolezal, я взглянул на источник Owin и System.Web.

Проблема в том, что System.Web имеет свой собственный основной источник информации о cookie, а не заголовок Set-Cookie. Овин знает только о заголовке Set-Cookie. Обходной путь должен удостовериться, что любые куки, установленные Owin, также установлены в HttpContext.Current.Response.Cookiesколлекции.

Я сделал небольшое промежуточное программное обеспечение ( источник , nuget ), которое делает именно это и предназначено для размещения непосредственно над регистрацией промежуточного программного обеспечения cookie.

app.UseKentorOwinCookieSaver();

app.UseCookieAuthentication(new CookieAuthenticationOptions());

1
Попробую. Так как после asp.net Identity 2.2.0-alpha1 у меня начались проблемы не только при входе в систему, но и при выходе пользователя из системы (пользователь не будет выходить из системы при выходе из системы, щелкните | обычно, в случае, если я оставил сайт открытым некоторое время ничего не делая |) .. И после установки сеанса непосредственно перед тем, как пользователь входит в систему, решается проблема входа в систему, но проблема выхода из системы сохраняется .. Спасибо за ваши усилия .. Кстати, есть ли что-то, что я должен сделать, кроме установки посылка?
— wooer

Вы должны активировать его app.UseKentorCookieMiddlewareSaver();в Startup.Auth.cs. Он также должен обрабатывать очистку cookie для выхода из системы.
— Андерс Абель

Большое спасибо, Андерс Абель, и вход, и выход из системы теперь работают нормально. Но код в приведенном выше комментарии необходимо изменить (потому что я следовал за ним :), но безуспешно), чтобы он был: app.UseKentorOwinCookieSaver()и, возможно, был включен в ваш первоначальный ответ, как на странице пакета GitHub .
— wooer

1
Спасибо, что заметили неверный документ. На самом деле это уже исправлено на странице GitHub, но я также обновил свой ответ здесь.
— Андерс Абель

@AndersAbel Я пытаюсь добавить регистрацию в Meetup для этого проекта github: github.com/owin-middleware/OwinOAuthProviders ''. Я добавил Asana на днях, и у меня не было проблем, но по какой-то причине в Meetup метод await AuthenticationManager.GetExternalLoginInfoAsync () в Account // ExternalLoginCallback возвращает ноль. К сожалению, ваш пакет NuGet не решил мою проблему. Мне было интересно, если у вас есть время, чтобы рассмотреть со мной, как вы могли бы лучше решить проблему и подтолкнуть к вашему проекту.
— Энтони Руффино

42

Короче говоря, менеджер файлов cookie .NET победит менеджер файлов cookie OWIN и перезапишет файлы cookie, установленные на слое OWIN . Исправление заключается в использовании класса SystemWebCookieManager, предоставленного в качестве решения для проекта Katana здесь . Вам нужно использовать этот класс или аналогичный ему, что заставит OWIN использовать менеджер файлов cookie .NET, чтобы не было несоответствий :

public class SystemWebCookieManager : ICookieManager
{
    public string GetRequestCookie(IOwinContext context, string key)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
        var cookie = webContext.Request.Cookies[key];
        return cookie == null ? null : cookie.Value;
    }

    public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);

        bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
        bool pathHasValue = !string.IsNullOrEmpty(options.Path);
        bool expiresHasValue = options.Expires.HasValue;

        var cookie = new HttpCookie(key, value);
        if (domainHasValue)
        {
            cookie.Domain = options.Domain;
        }
        if (pathHasValue)
        {
            cookie.Path = options.Path;
        }
        if (expiresHasValue)
        {
            cookie.Expires = options.Expires.Value;
        }
        if (options.Secure)
        {
            cookie.Secure = true;
        }
        if (options.HttpOnly)
        {
            cookie.HttpOnly = true;
        }

        webContext.Response.AppendCookie(cookie);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        AppendResponseCookie(
            context,
            key,
            string.Empty,
            new CookieOptions
            {
                Path = options.Path,
                Domain = options.Domain,
                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            });
    }
}

При запуске приложения просто назначьте его при создании зависимостей OWIN:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    ...
    CookieManager = new SystemWebCookieManager()
    ...
});

Подобный ответ был предоставлен здесь, но он не включает всю базу кода, необходимую для решения проблемы, поэтому я вижу необходимость добавить его здесь, потому что внешняя ссылка на проект Katana может быть недоступна, и это должно быть полностью записано как решение здесь также.


спасибо, его работа меня, но я также очищаю всю сессию, вызывая этот ControllerContext.HttpContext.Session.RemoveAll (); в externallogincallback функции
— Аднан

Применимо к ASP.NET Webforms 4.6.1 ? Мой webApp используетASP.NET Webforms, OWIN, ADFS
— Kiquenet

@Kiquenet Использует ли ваше веб-приложение куки OWIN? Тогда да.
— Александру

В коде Startup.ConfigureAuthу нас есть app.UseCookieAuthenticationи app.UseWsFederationAuthenticationи наконец app.UseStageMarker
— Kiquenet

@Alexandru Вы могли бы рассмотреть возможность редактирования, моя команда столкнулась с этой ошибкой, и она была редкой и случайной, она скрывалась от нас в средах DEV и UAT. Эта цитата из вашего ответа не подходит для нас: «.NET cookie manager всегда победит». Это было бы легко найти и исправить, если бы файлы cookie OWIN всегда перезаписывались, ни одно из нашего промежуточного программного обеспечения OIDC не смогло бы сойти с наших рабочих станций. Но случайность означала, что ошибка добралась до производства за 2 дня, прежде чем она достигла нас в масштабе (половина наших внутренних пользователей не могла войти через AAD). Не возражаете, если я уберу слово «всегда» из вашего ответа?
— yzorg

17

Команда Katana ответила на вопрос, поднятый Томасом Долезаром, и разместила документацию об обходных путях :

Обходные пути делятся на две категории. Одним из них является переконфигурирование System.Web, чтобы избежать использования коллекции Response.Cookies и перезаписи файлов cookie OWIN. Другой подход заключается в повторной настройке затронутых компонентов OWIN, чтобы они записывали файлы cookie непосредственно в коллекцию Response.Cookies System.Web.

  • Убедитесь, что сеанс установлен до проверки подлинности. Конфликт между файлами cookie System.Web и Katana происходит по запросу, поэтому приложение может установить сеанс по какому-либо запросу до процесса проверки подлинности. Это должно быть легко сделать, когда пользователь впервые прибывает, но это может быть труднее гарантировать позже, когда сеанс или файлы cookie авторизации истекают и / или должны быть обновлены.
  • Отключите SessionStateModule - если приложение не полагается на информацию о сеансе, но модуль сеанса по-прежнему устанавливает файл cookie, который вызывает вышеуказанный конфликт, вы можете отключить модуль состояния сеанса.
  • Переконфигурируйте CookieAuthenticationMiddleware для прямой записи в коллекцию cookie System.Web.
app.UseCookieAuthentication(new CookieAuthenticationOptions
                                {
                                    // ...
                                    CookieManager = new SystemWebCookieManager()
                                });

См. Реализацию SystemWebCookieManager из документации (ссылка выше)

Больше информации здесь

редактировать

Ниже приведены шаги, которые мы предприняли для решения проблемы. И 1., и 2. решили проблему также отдельно, но мы решили применить оба на всякий случай:

1. Используйте SystemWebCookieManager

2. Установите переменную сеанса:

protected override void Initialize(RequestContext requestContext)
{
    base.Initialize(requestContext);

    // See http://stackoverflow.com/questions/20737578/asp-net-sessionid-owin-cookies-do-not-send-to-browser/
    requestContext.HttpContext.Session["FixEternalRedirectLoop"] = 1;
}

(примечание: метод Initialize, описанный выше, является логическим местом для исправления, потому что base.Initialize делает Session доступным. Однако исправление также можно применить позже, поскольку в OpenId сначала выполняется анонимный запрос, затем перенаправляется к поставщику OpenId, а затем возвращается к приложению. Проблемы будут возникать после перенаправления обратно в приложение, в то время как исправление устанавливает переменную сеанса уже во время первого анонимного запроса, таким образом, устраняя проблему до того, как произойдет какое-либо перенаправление)

Редактировать 2

Скопируйте из проекта Katana 2016-05-14:

Добавь это:

app.UseCookieAuthentication(new CookieAuthenticationOptions
                                {
                                    // ...
                                    CookieManager = new SystemWebCookieManager()
                                });

...и это:

public class SystemWebCookieManager : ICookieManager
{
    public string GetRequestCookie(IOwinContext context, string key)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
        var cookie = webContext.Request.Cookies[key];
        return cookie == null ? null : cookie.Value;
    }

    public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);

        bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
        bool pathHasValue = !string.IsNullOrEmpty(options.Path);
        bool expiresHasValue = options.Expires.HasValue;

        var cookie = new HttpCookie(key, value);
        if (domainHasValue)
        {
            cookie.Domain = options.Domain;
        }
        if (pathHasValue)
        {
            cookie.Path = options.Path;
        }
        if (expiresHasValue)
        {
            cookie.Expires = options.Expires.Value;
        }
        if (options.Secure)
        {
            cookie.Secure = true;
        }
        if (options.HttpOnly)
        {
            cookie.HttpOnly = true;
        }

        webContext.Response.AppendCookie(cookie);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        AppendResponseCookie(
            context,
            key,
            string.Empty,
            new CookieOptions
            {
                Path = options.Path,
                Domain = options.Domain,
                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            });
    }
}

Я нахожу этот ответ намного проще и легче решить проблему. Спасибо, - Может быть, я говорил слишком внезапно. Это не решило мою проблему.
— JCS

@JCS Включены шаги, которые мы предприняли для решения проблемы. Вы узнали, была ли ваша проблема связана?
— Томиус

Я использую Web Api 2 + промежуточное программное обеспечение Owin + кэш Redis для управления сессиями для аутентификации. Я пытался использовать SystemWebCookieManager, и это не решило проблему, которая возникала у меня, когда не устанавливались файлы cookie для аутентификации. Использование «UseKentorOwinCookieSaver» решило эту проблему, но мне не слишком нравятся дополнительные внешние зависимости ...
— JCS

Очистка сессии работала для меня. Внешняя зависимость не требуется. Поместите это ControllerContext.HttpContext.Session.RemoveAll();в свои ExternalLogin()действия, прежде чем звонить ChallengeResult(). Не знаю, лучшее ли это решение, но самое простое.
— Алиссон,

1
@chemitax, конечно, просто учтите, что ?.(условно-нулевой оператор) работает только в C # 6.
— Alisson

5

Ответы уже были предоставлены, но в owin 3.1.0 есть класс SystemWebChunkingCookieManager, который можно использовать.

https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Host.SystemWeb/SystemWebChunkingCookieManager.cs

https://raw.githubusercontent.com/aspnet/AspNetKatana/c33569969e79afd9fb4ec2d6bdff877e376821b2/src/Microsoft.Owin.Host.SystemWeb/SystemWebChunkingCookieManager.cs

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    ...
    CookieManager = new SystemWebChunkingCookieManager()
    ...
});

Это все еще проблема в 3.1.0?
— киберконт

1
Да, это все еще проблема в 3.1.0 для меня, и он нуждался в этом менеджере файлов cookie, поскольку по умолчанию это все еще ChunkingCookieManager.
— Джонмейер

где можно использовать? и как?
— Simon_Weaver

@ jonmeyer спасибо. Я думаю, что вчера я пропустил различие между SystemCCM и CCM, поэтому я обязательно проверю это
— Simon_Weaver

даже после добавления вышеуказанной строки это не работает для меня. Я использую версию 3.1.0. В основном я могу войти в первый раз, но после выхода из системы это не позволяет мне войти.
— Митин Диксит

3

Если вы сами устанавливаете файлы cookie в промежуточном программном обеспечении OWIN, то, OnSendingHeadersкажется, использование этой проблемы обходит вас .

Например, с помощью приведенного ниже кода owinResponseCookie2будет установлено, хотя owinResponseCookie1это не так:

private void SetCookies()
{
    var owinContext = HttpContext.GetOwinContext();
    var owinResponse = owinContext.Response;

    owinResponse.Cookies.Append("owinResponseCookie1", "value1");

    owinResponse.OnSendingHeaders(state =>
    {
        owinResponse.Cookies.Append("owinResponseCookie2", "value2");
    },
    null);

    var httpResponse = HttpContext.Response;
    httpResponse.Cookies.Remove("httpResponseCookie1");
}

3

Я столкнулся с аналогичной проблемой в Visual Studio 2017 и .net MVC 5.2.4 , обновление Nuget Microsoft.Owin.Security.Google до последней версии, которая в настоящее время является 4.0.1, работает для меня! Надеюсь, это поможет кому-то!


1
Спас мой бекон на этом! Возникла проблема с Android Chrome, которая специально теряла аутентификацию наугад. Больше ничего в этой теме не работало. Я использую VS2019 и ASP MVC 5.
— zfrank

2

Самое быстрое однострочное кодовое решение:

HttpContext.Current.Session["RunSession"] = "1";

Просто добавьте эту строку перед методом CreateIdentity:

HttpContext.Current.Session["RunSession"] = "1";
var userIdentity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
_authenticationManager.SignIn(new AuthenticationProperties { IsPersistent = rememberLogin }, userIdentity);

1
Где вы положили этот код HttpContext.Current.Session["RunSession"] = "1";? в Globa.asax Session_Start ?
— Kiquenet

1
На самом деле это самое простое и быстрое решение, доступное до тех пор, пока решение этой проблемы не будет включено в Framework (уже объявлено, что оно будет) - я бы, например, предпочел бы однострочник, а не класс + кучу зависимостей , Это решение недооценивается ИМХО.
— Der Zinger

Я добавил его в свой AuthManager вверху метода IssueAuthToken
— Александр Трофимов,

1

У меня был тот же симптом, что заголовок Set-Cookie не отправлялся, но ни один из этих ответов мне не помог. Все работало на моем локальном компьютере, но при развертывании в производство заголовки set-cookie никогда не устанавливались.

Оказывается, это было сочетание использования пользовательского CookieAuthenticationMiddlewareс WebApi вместе с поддержкой сжатия WebApi.

К счастью, я использовал ELMAH в своем проекте, который позволил мне записать это исключение:

Сервер System.Web.HttpException не может добавить заголовок после отправки заголовков HTTP.

Что привело меня к этой проблеме GitHub

По сути, если у вас странная установка, как у меня, вы захотите отключить сжатие для ваших контроллеров / методов WebApi, которые устанавливают куки, или попробуйте OwinServerCompressionHandler.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.