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),
            });
    }
}
thomius
источник
Я нахожу этот ответ намного проще и легче решить проблему. Спасибо, - Может быть, я говорил слишком внезапно. Это не решило мою проблему.
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()
    ...
});
jonmeyer
источник
Это все еще проблема в 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");
}
Appetere
источник
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.

Хью Джеффнер
источник