У меня странная проблема с использованием аутентификации файла 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 (в тестировании)
источник
Ответы:
Я столкнулся с той же проблемой и проследил причину реализации хостинга OWIN ASP.NET. Я бы сказал, что это ошибка.
Некоторый фон
Мои выводы основаны на следующих версиях сборки:
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, вы рискуете.
Например, это работает, и оба куки правильно отправляются в браузер ...
Но это не так, и OwinCookie "потерян" ...
Оба протестированы из VS2013, IISExpress и шаблон проекта MVC по умолчанию.
источник
Начав с большого анализа @TomasDolezal, я взглянул на источник Owin и System.Web.
Проблема в том, что System.Web имеет свой собственный основной источник информации о cookie, а не заголовок Set-Cookie. Овин знает только о заголовке Set-Cookie. Обходной путь должен удостовериться, что любые куки, установленные Owin, также установлены в
HttpContext.Current.Response.Cookies
коллекции.Я сделал небольшое промежуточное программное обеспечение ( источник , nuget ), которое делает именно это и предназначено для размещения непосредственно над регистрацией промежуточного программного обеспечения cookie.
источник
app.UseKentorCookieMiddlewareSaver();
в Startup.Auth.cs. Он также должен обрабатывать очистку cookie для выхода из системы.app.UseKentorOwinCookieSaver()
и, возможно, был включен в ваш первоначальный ответ, как на странице пакета GitHub .Короче говоря, менеджер файлов cookie .NET победит менеджер файлов cookie OWIN и перезапишет файлы cookie, установленные на слое OWIN . Исправление заключается в использовании класса SystemWebCookieManager, предоставленного в качестве решения для проекта Katana здесь . Вам нужно использовать этот класс или аналогичный ему, что заставит OWIN использовать менеджер файлов cookie .NET, чтобы не было несоответствий :
При запуске приложения просто назначьте его при создании зависимостей OWIN:
Подобный ответ был предоставлен здесь, но он не включает всю базу кода, необходимую для решения проблемы, поэтому я вижу необходимость добавить его здесь, потому что внешняя ссылка на проект Katana может быть недоступна, и это должно быть полностью записано как решение здесь также.
источник
ASP.NET Webforms, OWIN, ADFS
Startup.ConfigureAuth
у нас естьapp.UseCookieAuthentication
иapp.UseWsFederationAuthentication
и наконецapp.UseStageMarker
Команда Katana ответила на вопрос, поднятый Томасом Долезаром, и разместила документацию об обходных путях :
См. Реализацию SystemWebCookieManager из документации (ссылка выше)
Больше информации здесь
редактировать
Ниже приведены шаги, которые мы предприняли для решения проблемы. И 1., и 2. решили проблему также отдельно, но мы решили применить оба на всякий случай:
1. Используйте SystemWebCookieManager
2. Установите переменную сеанса:
(примечание: метод Initialize, описанный выше, является логическим местом для исправления, потому что base.Initialize делает Session доступным. Однако исправление также можно применить позже, поскольку в OpenId сначала выполняется анонимный запрос, затем перенаправляется к поставщику OpenId, а затем возвращается к приложению. Проблемы будут возникать после перенаправления обратно в приложение, в то время как исправление устанавливает переменную сеанса уже во время первого анонимного запроса, таким образом, устраняя проблему до того, как произойдет какое-либо перенаправление)
Редактировать 2
Скопируйте из проекта Katana 2016-05-14:
Добавь это:
...и это:
источник
ControllerContext.HttpContext.Session.RemoveAll();
в своиExternalLogin()
действия, прежде чем звонитьChallengeResult()
. Не знаю, лучшее ли это решение, но самое простое.?.
(условно-нулевой оператор) работает только в C # 6.Ответы уже были предоставлены, но в 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
источник
Если вы сами устанавливаете файлы cookie в промежуточном программном обеспечении OWIN, то,
OnSendingHeaders
кажется, использование этой проблемы обходит вас .Например, с помощью приведенного ниже кода
owinResponseCookie2
будет установлено, хотяowinResponseCookie1
это не так:источник
Я столкнулся с аналогичной проблемой в Visual Studio 2017 и .net MVC 5.2.4 , обновление Nuget Microsoft.Owin.Security.Google до последней версии, которая в настоящее время является 4.0.1, работает для меня! Надеюсь, это поможет кому-то!
источник
Самое быстрое однострочное кодовое решение:
Просто добавьте эту строку перед методом CreateIdentity:
источник
HttpContext.Current.Session["RunSession"] = "1";
? в Globa.asaxSession_Start
?У меня был тот же симптом, что заголовок Set-Cookie не отправлялся, но ни один из этих ответов мне не помог. Все работало на моем локальном компьютере, но при развертывании в производство заголовки set-cookie никогда не устанавливались.
Оказывается, это было сочетание использования пользовательского
CookieAuthenticationMiddleware
с WebApi вместе с поддержкой сжатия WebApi.К счастью, я использовал ELMAH в своем проекте, который позволил мне записать это исключение:
Что привело меня к этой проблеме GitHub
По сути, если у вас странная установка, как у меня, вы захотите отключить сжатие для ваших контроллеров / методов WebApi, которые устанавливают куки, или попробуйте
OwinServerCompressionHandler
.источник