ASP.NET_SessionId + OWIN Файли cookie не надсилаються до браузера


145

У мене є дивна проблема із використанням автентифікації файлів cookie Owin.

Коли я запускаю IIS-сервер, автентичність працює ідеально на IE / Firefox та Chrome.

Я почав робити тестування з використанням автентифікації та входу на різних платформах, і зіткнувся з дивною помилкою. Спорадично, Owin Framework / IIS просто не надсилає файли cookie браузерам. Я введу ім’я користувача та пароль, які правильно виконуються, але файл 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 + моє печиво для автентифікації. 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 відрізняється. Що я бачу, це те, що мої сеанси Овіна залишаються живими довше, ніж мої сеанси ASP через якийсь механізм. Тому при вході в систему: 1.) У мене є авторизований сеанс на основі cookied 2.) Я встановив кілька змінних сеансів

Мої змінні сеансу (2) "відмирають" перед змінною сеансу cookie Owin змушують повторно входити в систему, що викликає несподівану поведінку протягом усієї моєї програми. (Користувач увійшов, але насправді не ввійшов)

Оновлення 3B

Після деякого копання я побачив деякі коментарі на сторінці, де сказано, що "форми" аутентифікації та час очікування сеансу повинні збігатися. Я думаю, що обидва вони синхронізовані, але з будь-якої причини вони не синхронізовані.

Короткий зміст обхідних питань

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

2) [Експериментальний], якщо ви зберігаєте файли cookie, переконайтесь, що час / довжина OWIN більше, ніж ваш сеанс тайм-аут у вашому web.config (для тестування)


1
Можна підтвердити, що додавання сеансового виклику до ActionResult Login та ActionResult ExternalLogin вирішило цю проблему. Я впевнений, що потрібен лише один, але в мене обоє.
Скотт

Дякую! ... Додавання сесії в ExternalLogin виправлено це для мене ... це магія вуду ... я вже витратив 6 годин на пошук цієї проблеми ..
xdev

Відповіді:


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 ( 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 невірно. Ідентифікатори сеансу не створюються модулем стану сеансу, а стан колекції System.Web.HttpResponse.Cookies не виявляється як змінений . У цьому випадку файли cookie OWIN надсилаються правильно до браузера, і вхід працює.

Випадок 2 - Сесія була використана десь у додатку, але не раніше, ніж користувач намагається пройти автентифікацію

System.Web.SessionState.SessionStateModule , s_sessionEverSet властивість вірно. Ідентифікатори сеансу генеруються SessionStateModule , ASP.NET_SessionId додається до колекції System.Web.HttpResponse.Cookies, але він видаляється пізніше протягом життя запиту, оскільки сеанс користувача фактично порожній. У цьому випадку стан колекції System.Web.HttpResponse.Cookies виявляється як змінений, а заголовок Set-Cookie спочатку очищається перед тим, як файли cookie серіалізуються до значення заголовка.

У цьому випадку файли cookie-відповіді OWIN "втрачаються", а користувач не автентифікується і перенаправляється назад на сторінку входу.

Випадок 3 - сесія використовується перед тим, як користувач намагається пройти автентифікацію

System.Web.SessionState.SessionStateModule , s_sessionEverSet властивість вірно. Ідентифікатори сеансу генеруються користувачем SessionStateModule , ASP.NET_SessionId додано до System.Web.HttpResponse.Cookies . Завдяки внутрішній оптимізації в System.Web.HttpCookieCollection і System.Web.HttpResponse.GenerateResponseHeadersForCookies () Заголовок Set-Cookie НЕ спочатку видаляється, а лише оновлюється.

У цьому випадку як файли cookie автентифікації OWIN, так і файли cookie ASP.NET_SessionId надсилаються у відповідь, і вхід працює.


Більш загальна проблема з файлами cookie

Як бачите, проблема є більш загальною і не обмежується сеансом ASP.NET. Якщо ви розміщуєте OWIN через Microsoft.Owin.Host.SystemWeb, і ви / щось безпосередньо використовуєте System.Web.HttpResponse.Cookies колекція, ви ризикуєте.

Наприклад це працює, і обидва файли cookie правильно відправлені в браузер ...

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.codeplex.com/workitem/197 , тому, можливо, хтось там прокоментує.
Томаш Долезал

11
Це досить серйозний недолік, тим більше, що вони упаковували власний шаблон для vs2013.
Пьотр Стулінський

2
Для всіх, хто хоче це дослідити далі, я створив тестовий проект на сайті github.com/Neilski/IdentityBugDemo
Neilski

1
Натрапили на цю проблему через використання Controller.TempData, який використовує Session в якості резервного магазину. Може легко відтворити неможливість входу в систему, якщо файл cookie ASP_NET.SessionId не існує з попереднього запиту.
kingdango

2
Нарешті! Що це за дивне питання. Дякую. Це питання залишається питанням протягом двох років після написання цієї відповіді.
Spivonious

43

Починаючи з чудового аналізу @TomasDolezal, я ознайомився як з джерелом Owin, так і з System.Web.

Проблема полягає в тому, що System.Web має власне головне джерело інформації про файли cookie, і це не заголовок Set-Cookie. Овін знає лише про заголовок Set-Cookie. Вирішення проблеми полягає в тому, щоб переконатися, що будь-які файли cookie, встановлені Овіном, також встановлені в HttpContext.Current.Response.Cookiesколекції.

Я створив невелике проміжне програмне забезпечення ( джерело , нугет ), яке робить саме це, що призначене для розміщення безпосередньо над реєстрацією проміжних програм cookie.

app.UseKentorOwinCookieSaver();

app.UseCookieAuthentication(new CookieAuthenticationOptions());

1
Спробую це. Оскільки після asp.net Identity 2.2.0-alpha1 у мене виникли проблеми не тільки при вході в систему, але і при виході з користувача (користувач не виходитиме з системи виходу, натисніть | як правило, у випадку, коли я залишив веб-сайт відкритим на якийсь час не роблячи нічого |) .. І після встановлення сеансу безпосередньо перед тим, як користувач увійде в систему для вирішення проблеми входу, але проблема виходу зберігається .. Дякую за ваші зусилля .. До речі, чи є щось, що я повинен зробити, окрім установки пакунок?
вурше

Активувати його потрібно app.UseKentorCookieMiddlewareSaver();в Startup.Auth.cs. Він також повинен обробляти очищення файлів cookie виходу.
Андерс Абель

Дякую тобі, Андерс Абель, і вхід, і вихід із системи виходять нормально. Але код вищевказаного коментаря потрібно змінити (бо я дотримувався його :) без жодного успіху), щоб він був:app.UseKentorOwinCookieSaver() і, можливо, був включений до вас оригінальною відповіддю, як на сторінці GitHub пакета .
wooer

1
Дякуємо, що помітили неправильний документ. Це фактично вже зафіксовано на сторінці GitHub, але я оновив свою відповідь і тут.
Андерс Абель

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

42

Якщо коротко, менеджер файлів cookie .NET переможе менеджер файлів cookie OWIN і замінить файли cookie, встановлені на шарі OWIN . Виправлення полягає у використанні класу SystemWebCookieManager, наданого тут як рішення для проекту Katana . Вам потрібно використовувати цей клас або подібний до нього, що змусить OWIN використовувати диспетчер файлів .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
adnan

Чи застосовується до веб- форм ASP.NET 4.6.1 ? Мій webApp використовуєASP.NET Webforms, OWIN, ADFS
Kiquenet

@Kiquenet Чи використовує ваш веб-додаток файли cookie OWIN? Тоді так.
Олександру

У коді у Startup.ConfigureAuthнас є app.UseCookieAuthenticationі, app.UseWsFederationAuthenticationнарешті, app.UseStageMarker
Кікенет

@Alexandru Ви можете розглянути можливість редагування. Моя команда потрапила в цю помилку, і вона була рідкісною і випадковою, вона ховалася від нас через середовища DEV та UAT. Ця цитата з вашої відповіді не стосується нас: ".NET менеджер файлів cookie завжди виграє." Це було б легко знайти та виправити, якби файли cookie OWIN завжди перезаписувались, жодне з наших програмного забезпечення OIDC не вимкнуло б це з наших робочих станцій розробників. Але випадковість означала, що помилка зробила це все до виробництва за 2 дні, перш ніж вона потрапила до нас у масштабі (половина наших внутрішніх застосувань не змогла увійти через AAD). Майте на увазі, якщо я видалю слово "завжди" з вашої відповіді?
yzorg

17

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

Обхідні шляхи поділяються на дві категорії. Перша - це перенастроювання System.Web, щоб уникнути використання колекції Response.Cookies та перезапис файлів cookie OWIN. Інший підхід полягає в повторному налаштуванні уражених компонентів OWIN, щоб вони записували файли cookie безпосередньо в колекцію System.Web's Response.Cookies.

  • Переконайтеся, що сеанс встановлений до аутентифікації: конфлікт між файлами 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 робить сеанс доступним. Однак виправлення також може бути застосовано пізніше, оскільки у 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
@chemitaxis впевнений, просто врахуйте, що ?.(нульовий умовний оператор) працює лише на C # 6.
Еліссон,

5

Відповіді вже надано, але у власній 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?
cyberconte

1
Так, це все ще проблема в 3.1.0 для мене, і мені потрібен цей менеджер файлів cookie, оскільки типовим є ще ChunkingCookieManager.
jonmeyer

можна використовувати де? і як?
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 ?
Кікенет

1
Насправді це найпростіше і найшвидше рішення, і поки вирішення цієї проблеми не буде включено до Рамок (вже оголошено, що буде) - я, наприклад, вважаю за краще однолінійний, а не клас + купу залежностей . Це рішення є недооціненим ІМХО.
Der Zinger

Я додав його до свого AuthManager вгорі методу IssueAuthToken
Олександр Трофімов

1

У мене був такий самий симптом того, що заголовок Set-Cookie не надсилався, але жодна з цих відповідей мені не допомогла. Все працювало на моїй локальній машині, але при розгортанні для виробництва заголовки файлів cookie ніколи не встановлюються.

Виявляється, це було поєднанням використання користувальницького CookieAuthenticationMiddlewareз WebApi разом із підтримкою стиснення WebApi

На щастя, я використовував ELMAH у своєму проекті, який дозволив мені зареєструвати цей виняток:

System.Web.HttpException Server не може додавати заголовок після надсилання заголовків HTTP.

Що призвело мене до цього випуску GitHub

В основному, якщо у вас є дивна установка на зразок моєї, ви захочете відключити компресію для своїх контролерів / методів WebApi, які встановлюють файли cookie, або спробуйте OwinServerCompressionHandler.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.