FormsAuthentication.Функция SignOut() не выводит пользователя из системы
-
03-07-2019 - |
Вопрос
Я слишком долго бился об это головой.Как мне запретить пользователю просматривать страницы сайта после выхода из системы с помощью FormsAuthentication.Выход из системы?Я бы ожидал, что это сработает:
FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();
Но это не так.Если я введу URL-адрес напрямую, я все равно смогу перейти на нужную страницу.Я давно не пользовался функцией roll-your-own security, поэтому забыл, почему это не работает.
Решение
Пользователи по-прежнему могут просматривать ваш веб-сайт, поскольку файлы cookie не очищаются при вызове FormsAuthentication.SignOut ()
, и они аутентифицируются при каждом новом запросе. В документации MS написано, что cookie будет очищен, но это не так, ошибка?
То же самое с Session.Abandon ()
, cookie все еще там.
Вы должны изменить свой код на это:
FormsAuthentication.SignOut();
Session.Abandon();
// clear authentication cookie
HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie1.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie1);
// clear session cookie (not necessary for your current problem but i would recommend you do it anyway)
SessionStateSection sessionStateSection = (SessionStateSection)WebConfigurationManager.GetSection("system.web/sessionState");
HttpCookie cookie2 = new HttpCookie(sessionStateSection.CookieName, "");
cookie2.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie2);
FormsAuthentication.RedirectToLoginPage();
HttpCookie
находится в пространстве имен System.Web
. Справочник по MSDN . р>
Другие советы
Похоже, у вас не настроен раздел авторизации web.config. Ниже приведен пример.
<authentication mode="Forms">
<forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
Используя две из приведенных выше публикации x64igor и Phil Haselden, решили эту проблему:
1.x64igor привел пример для выполнения выхода из системы:
Сначала вам нужно Очистите файлы cookie аутентификации и сеансовые файлы cookie передавая обратно пустые файлы cookie в ответе на выход из системы.
public ActionResult LogOff() { FormsAuthentication.SignOut(); Session.Clear(); // This may not be needed -- but can't hurt Session.Abandon(); // Clear authentication cookie HttpCookie rFormsCookie = new HttpCookie( FormsAuthentication.FormsCookieName, "" ); rFormsCookie.Expires = DateTime.Now.AddYears( -1 ); Response.Cookies.Add( rFormsCookie ); // Clear session cookie HttpCookie rSessionCookie = new HttpCookie( "ASP.NET_SessionId", "" ); rSessionCookie.Expires = DateTime.Now.AddYears( -1 ); Response.Cookies.Add( rSessionCookie );
2.Фил Хазельден привел приведенный выше пример того, как предотвратить кэширование после выхода из системы:
Тебе нужно Сделайте недействительным кэш на стороне клиента с помощью ответа.
// Invalidate the Cache on the Client Side Response.Cache.SetCacheability( HttpCacheability.NoCache ); Response.Cache.SetNoStore(); // Redirect to the Home Page (that should be intercepted and redirected to the Login Page first) return RedirectToAction( "Index", "Home" ); }
Ключевым моментом здесь является то, что вы говорите "Если я введу URL-адрес напрямую ...".
По умолчанию при проверке подлинности с помощью форм браузер кэширует страницы для пользователя. Поэтому, выбирая URL-адрес непосредственно из раскрывающегося списка адресов браузера или вводя его, МОЖЕТ получить страницу из кэша браузера и никогда не возвращаться на сервер для проверки аутентификации / авторизации. Решением этой проблемы является предотвращение кэширования на стороне клиента в событии Page_Load каждой страницы или в OnLoad () вашей базовой страницы:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Вы также можете позвонить:
Response.Cache.SetNoStore();
Я тоже с этим раньше боролся.
Вот аналогия с тем, что, похоже, происходит ... Новый посетитель, Джо, заходит на сайт и входит через страницу входа с помощью FormsAuthentication. ASP.NET генерирует новую личность для Джо и дает ему cookie. Это печенье похоже на ключ от дома, и пока Джо возвращается с этим ключом, он может открыть замок. Каждый посетитель получает новый ключ и новый замок для использования.
Когда вызывается FormsAuthentication.SignOut ()
, система сообщает Джо потерять ключ. Обычно это работает, поскольку у Джо больше нет ключа, он не может войти.
Однако, если Джо когда-нибудь вернется, а получил этот потерянный ключ, его снова впустят!
Из того, что я могу сказать, нет способа заставить ASP.NET изменить замок на двери!
Я могу жить с этим, вспоминая имя Джо в переменной Session. Когда он выходит из системы, я прекращаю сеанс, поэтому у меня больше нет его имени. Позже, чтобы проверить, разрешен ли ему вход, я просто сравниваю его Identity.Name с тем, что имеет текущий сеанс, и если они не совпадают, он не является действительным посетителем.
Короче говоря, для веб-сайта НЕ полагайтесь на User.Identity.IsAuthenticated
, не проверяя также переменные сеанса!
Это работает для меня
public virtual ActionResult LogOff()
{
FormsAuthentication.SignOut();
foreach (var cookie in Request.Cookies.AllKeys)
{
Request.Cookies.Remove(cookie);
}
foreach (var cookie in Response.Cookies.AllKeys)
{
Response.Cookies.Remove(cookie);
}
return RedirectToAction(MVC.Home.Index());
}
После долгих поисков, наконец, это сработало для меня. Надеюсь, это поможет.
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
return RedirectToAction("Index", "Home");
}
<li class="page-scroll">@Html.ActionLink("Log off", "LogOff", "Account")</li>
Код, который вы разместили, выглядит так, как будто он должен правильно удалить маркер аутентификации форм, поэтому вполне возможно, что рассматриваемые папки / страницы фактически не защищены.
Подтвердили ли вы, что доступ к страницам невозможен до того, как произойдет вход в систему?
Можете ли вы опубликовать используемые вами настройки web.config и код входа в систему?
Я писал базовый класс для всех своих Страниц и пришел к одной и той же проблеме.У меня был код, подобный следующему, и он не сработал.При трассировке управление переходит от оператора RedirectToLoginPage() к следующей строке без перенаправления.
if (_requiresAuthentication)
{
if (!User.Identity.IsAuthenticated)
FormsAuthentication.RedirectToLoginPage();
// check authorization for restricted pages only
if (_isRestrictedPage) AuthorizePageAndButtons();
}
Я выяснил, что есть два решения.Либо изменить проверку подлинности FormsAuthentication.RedirectToLoginPage();быть
if (!User.Identity.IsAuthenticated)
Response.Redirect(FormsAuthentication.LoginUrl);
ИЛИ изменить web.config, добавив
<authorization>
<deny users="?" />
</authorization>
Во втором случае, во время отслеживания, элемент управления не достиг запрошенной страницы.Он был немедленно перенаправлен на URL-адрес входа в систему до достижения точки останова.Следовательно, проблема не в методе SignOut(), а в методе перенаправления.
Я надеюсь, что это кому-нибудь поможет
С уважением
Я только что попробовал некоторые из предложенных здесь советов, и, хотя я смог использовать кнопку «Назад» в браузере, когда я щелкнул по выбору меню, токен [Authorize] для этого [ActionResult] отправил меня обратно на экран входа в систему. р>
Вот мой код выхода из системы:
FormsAuthentication.SignOut();
Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
HttpCookie cookie = HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
cookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(cookie);
}
Хотя функция возврата в браузере вернула меня назад и отобразила защищенное меню (я все еще над этим работаю), я не смог сделать ничего, что было защищено в приложении.
Надеюсь, это поможет
Я пробовал большинство ответов в этой теме, не повезло. Закончилось этим:
protected void btnLogout_Click(object sender, EventArgs e)
{
FormsAuthentication.Initialize();
var fat = new FormsAuthenticationTicket(1, "", DateTime.Now, DateTime.Now.AddMinutes(-30), false, string.Empty, FormsAuthentication.FormsCookiePath);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(fat)));
FormsAuthentication.RedirectToLoginPage();
}
Нашел его здесь: http://forums.asp.net/t/1306526. ASPX / 1 р>
Этот ответ технически идентичен Хосро. Пакманеш. Я публикую его, чтобы уточнить, чем его ответ отличается от других ответов в этой теме, и в каком случае его можно использовать.
В общем, чтобы очистить пользовательский сеанс, делая
HttpContext.Session.Abandon();
FormsAuthentication.SignOut();
будет эффективно выходить из системы. Однако , если в том же запросе вам нужно проверить Request.isAuthenticated
(как это часто бывает, например, в фильтре авторизации), то вы обнаружите, что
Request.isAuthenticated == true
даже после того, как вы сделали HttpContext.Session.Abandon ()
и FormsAuthentication.SignOut ()
.
Единственное, что сработало, это делал
AuthenticationManager.SignOut();
HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
Это эффективно устанавливает Request.isAuthenticated = false
.
Это начало происходить со мной, когда я установил аутентификацию > формы > Свойство пути в Web.config
. Устранение, которое решило проблему, и простой FormsAuthentication.SignOut ();
снова удалил cookie.
Возможно, вы входите из одного субдомена (sub1.domain.com) и затем пытаетесь выйти из другого субдомена (www.domain.com).
У меня была та же проблема, когда SignOut (), похоже, не смог правильно удалить тикет. Но только в конкретном случае, когда какая-то другая логика вызвала перенаправление. После того как я удалил этот второй редирект (заменил его сообщением об ошибке), проблема исчезла.
Проблема, возможно, заключалась в том, что страница перенаправлялась не в то время, поэтому не запускалась аутентификация.
У меня сейчас похожая проблема, и я считаю, что проблема в моем случае, так же как и в оригинальном постере, связана с перенаправлением. По умолчанию Response.Redirect вызывает исключение, которое сразу всплывает, пока не будет перехвачено, и перенаправление немедленно выполнено, я предполагаю, что это предотвращает передачу измененной коллекции файлов cookie клиенту. Если вы измените свой код для использования:
Response.Redirect("url", false);
Это предотвращает исключение и, по-видимому, позволяет правильно отправлять cookie клиенту.
Просто попробуйте отправить переменную сеанса, когда вы нажимаете войти. И на странице приветствия сначала проверьте, пуст ли этот сеанс, как это, при загрузке страницы или в событии Init:
if(Session["UserID"] == null || Session["UserID"] == "")
{
Response.Redirect("Login.aspx");
}
Для меня работает следующий подход. Я думаю, есть ли какая-либо ошибка после " FormsAuthentication.SignOut () " Заявление, SingOut не работает.
public ActionResult SignOut()
{
if (Request.IsAuthenticated)
{
FormsAuthentication.SignOut();
return Redirect("~/");
}
return View();
}
Вы тестируете / видите это поведение с помощью IE? Возможно, что IE обслуживает эти страницы из кэша. Общеизвестно, что IE трудно очистить кэш, и во многих случаях, даже после выхода из системы, введите URL-адрес одного из «защищенных» ключей. на страницах будет отображаться кэшированное содержимое ранее.
(Я видел такое поведение, даже когда вы входите в систему как другой пользователь, и IE отображает панель " Welcome " в верхней части страницы со старым именем пользователя. В настоящее время обычно перезагрузка обновляет его , но если он постоянен, это может быть проблемой кеширования.)
Выполнение Session.abandon () и уничтожение файла cookie работает довольно хорошо. Я использую mvc3, и похоже, что проблема возникает, если вы заходите на защищенную страницу, выходите из системы и просматриваете историю браузера. Ничего страшного, но все равно немного раздражает.
Попытка просмотреть ссылки в моем веб-приложении работает правильно.
Возможно, стоит отключить кэширование в браузере.
Для MVC это работает для меня:
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return Redirect(FormsAuthentication.GetRedirectUrl(User.Identity.Name, true));
}
Я хотел добавить некоторую информацию, чтобы помочь понять проблему. Проверка подлинности с помощью форм позволяет хранить пользовательские данные либо в файле cookie, либо в строке запроса URL-адреса. Метод, поддерживаемый вашим сайтом, можно настроить в файле web.config.
Метод SignOut удаляет информацию о билете проверки подлинности с помощью форм из файла cookie или URL-адреса , если CookiesSupported имеет значение false .
В то же время они говорят :
Одно из значений HttpCookieMode, которое указывает, является ли Приложение настроено для проверки подлинности без файлов cookie. <Сильный> Элемент по умолчанию - UseDeviceProfile .
Наконец, что касается UseDeviceProfile, они говорят :
Если для свойства CookieMode установлено значение UseDeviceProfile, CookiesSupported возвращает true, если браузер для текущий запрос поддерживает файлы cookie и перенаправление с помощью файлов cookie ; в противном случае свойство CookiesSupported вернет false.
Соединяя все это вместе, в зависимости от браузера пользователя, конфигурация по умолчанию может привести к тому, что CookiesSupported будет иметь true , что означает, что метод SignOut не удаляет билет из куки. Это кажется нелогичным, и я не знаю, почему это работает таким образом - я бы ожидал, что SignOut действительно выписывает пользователя при любых обстоятельствах.
Один из способов заставить SignOut работать самостоятельно - изменить режим файлов cookie на «UseCookies». (т. е. требуются файлы cookie) в файле web.config:
<authentication mode="Forms">
<forms loginUrl="~/Account/SignIn" cookieless="UseCookies"/>
</authentication>
Согласно моим тестам, это делает SignOut работающим само по себе за счет вашего сайта, теперь требующего, чтобы куки функционировали должным образом.
Помните, что WIF отказывается сообщать браузеру о необходимости очистки файлов cookie, если сообщение wsignoutcleanup из STS не соответствует URL-адресу с именем приложения из IIS, и я имею в виду ДЕЛО ЧУВСТВИТЕЛЬНО . WIF отвечает зеленой проверкой OK, но не отправит команду на удаление файлов cookie в браузер.
Итак, вам нужно обратить внимание на чувствительность к регистру ваших URL.
Например, ThinkTecture Identity Server сохраняет URL-адреса посещающих RP в одном файле cookie, но делает их все строчными. WIF получит сообщение wsignoutcleanup в нижнем регистре и сравнит его с именем приложения в IIS. Если он не совпадает, он не удаляет куки, но сообщит браузеру «ОК». Итак, для этого Identity Server мне нужно было написать все URL-адреса в web.config и имена всех приложений в IIS в нижнем регистре, чтобы избежать таких проблем.
Также не забудьте разрешить сторонние файлы cookie в браузере, если у вас есть приложения вне поддоменов STS, иначе браузер не удалит файлы cookie, даже если WIF скажет ему об этом.