FormsAuthentication.SignOut() не регистрирует пользователя
Слишком сильно промахнулся. Как я могу запретить пользователю просматривать страницы сайта после их выхода из системы с помощью FormsAuthentication.SignOut? Я бы ожидал, что это сделает:
FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();
Но это не так. Если я набираю URL-адрес напрямую, я все равно могу перейти на страницу. Я не использовал рулонную собственную безопасность, поэтому забываю, почему это не работает.
Ответы
Ответ 1
Пользователи могут просматривать веб-сайт, потому что 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.
Ответ 2
Звучит так, как будто у вас нет правильного раздела авторизации web.config. Ниже приведен пример.
<authentication mode="Forms">
<forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
Ответ 3
Используя две из приведенных выше сообщений от 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" );
}
Ответ 4
Ключевым моментом здесь является то, что вы говорите: "Если я набираю URL напрямую...".
По умолчанию при аутентификации форм браузер кэширует страницы для пользователя. Таким образом, выбирая URL-адрес непосредственно из раскрывающегося списка адреса браузера или вводя его, МОЖЕТ получить страницу из кеша браузера и никогда не возвращаться на сервер, чтобы проверить аутентификацию/авторизацию. Решением этого является предотвращение кеширования на стороне клиента в событии Page_Load каждой страницы или в OnLoad() на вашей базовой странице:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Вы также можете позвонить:
Response.Cache.SetNoStore();
Ответ 5
Я тоже боролся с этим.
Здесь аналогия для того, что, кажется, продолжается... Новый посетитель, Джо, приходит на сайт и регистрируется на странице входа с помощью FormsAuthentication. ASP.NET генерирует новый идентификатор для Joe и дает ему cookie. Этот файл cookie похож на ключ к дому, и пока Джо возвращается с этим ключом, он может открыть замок. Каждому посетителю предоставляется новый ключ и новый замок для использования.
Когда вызывается FormsAuthentication.SignOut()
, система сообщает Джо о потере ключа. Обычно это работает, поскольку у Джо больше нет ключа, он не может войти.
Однако, если Джо когда-нибудь вернется и у него есть потерянный ключ, он снова возвращается!
Из того, что я могу сказать, нет способа сказать ASP.NET изменить замок на двери!
Способ, которым я могу жить с этим, - запомнить имя Джо в переменной Session. Когда он выходит из системы, я покидаю сессию, поэтому у меня больше нет его имени. Позже, чтобы проверить, разрешен ли он, я просто сравниваю его Identity.Name с тем, что имеет текущий сеанс, и если они не совпадают, он не является действительным посетителем.
Короче говоря, для веб-сайта НЕ полагайтесь на User.Identity.IsAuthenticated
, не проверяя также свои переменные сеанса!
Ответ 6
Это работает для меня
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());
}
Ответ 7
После долгих поисков, наконец, это сработало для меня. Надеюсь, это поможет.
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>
Ответ 8
Код, который вы опубликовали, выглядит так, как будто он должен правильно удалить токен аутентификации форм, поэтому возможно, что папки/страницы не защищены.
Подтвердили ли вы, что страницы не могут быть доступны до входа в систему?
Можете ли вы опубликовать настройки web.config и код входа, который вы используете?
Ответ 9
Я писал базовый класс для всех моих страниц, и я пришел к той же проблеме.
У меня был код вроде следующего, и это не сработало. По трассировке управление переходит из инструкции 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() не является проблемой, метод перенаправления является одним из них.
Я надеюсь, что это может помочь кому-то
Привет
Ответ 10
Я только что попробовал некоторые из предложений здесь, и когда я смог использовать кнопку назад, когда я нажал на выбор меню, токен [Авторизовать] для этого [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);
}
Хотя функция back в браузере вернула меня и отобразила защищенное меню (я все еще работаю над этим), я не смог сделать ничего, что было защищено в приложении.
Надеюсь, что это поможет
Ответ 11
Я пробовал большинство ответов в этой теме, не повезло. Закончилось:
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
Ответ 12
Этот ответ технически идентичен Khosro.Pakmanesh. Я отправляю его, чтобы уточнить, как его ответ отличается от других ответов на эту тему и в каком случае его использовать.
Как правило, чтобы очистить сеанс пользователя, выполните
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
.
Ответ 13
Это началось со мной, когда я установил свойство authentication > forms > Path в Web.config
. Удалив это исправление проблемы, а простой FormsAuthentication.SignOut();
снова удалил файл cookie.
Ответ 14
Возможно, вы заходите из одного поддомена (sub1.domain.com), а затем пытаетесь выйти из другого поддомена (www.domain.com).
Ответ 15
У меня была такая же проблема, когда SignOut(), казалось бы, не смог правильно удалить билет. Но только в конкретном случае, когда какая-то другая логика вызвала перенаправление. После того как я удалил это второе перенаправление (заменил его сообщением об ошибке), проблема исчезла.
Проблема заключалась в том, что страница перенаправлялась в неподходящее время, поэтому не запускала аутентификацию.
Ответ 16
У меня сейчас аналогичная проблема, и я считаю, что проблема в моем случае, а также оригинальный плакат из-за перенаправления. По умолчанию Response.Redirect вызывает исключение, которое сразу же всплывает до тех пор, пока оно не будет обнаружено, и перенаправление будет немедленно выполнено, я предполагаю, что это предотвращает передачу измененной коллекции файлов cookie клиенту. Если вы измените свой код:
Response.Redirect("url", false);
Это предотвращает исключение и, как представляется, позволяет cookie быть отправлен обратно клиенту.
Ответ 17
Просто попробуйте отправить переменную сеанса при входе в систему.
И на странице приветствия сначала проверьте, пуст ли этот сеанс, как это, в загрузке страницы или в событии Init:
if(Session["UserID"] == null || Session["UserID"] == "")
{
Response.Redirect("Login.aspx");
}
Ответ 18
Вы тестируете/видите это поведение с помощью IE? Возможно, что IE обслуживает эти страницы из кеша. Как правило, сложно заставить IE очистить кеш-память, и так много раз, даже после выхода из системы, при вводе URL-адреса одной из "защищенных" страниц будет отображаться содержимое кэша раньше.
(Я видел это поведение, даже когда вы регистрировались как другой пользователь, а IE показывает панель приветствия в верхней части страницы со старым именем пользователя. В настоящее время обычно перезагрузка будет обновлять ее, но если он будет сохраняться, он все равно может быть проблемой кэширования.)
Ответ 19
Выполнение Session.abandon() и уничтожение файла cookie работает очень хорошо. Я использую mvc3, и похоже, что проблема возникает, если вы переходите на защищенную страницу, выходите из системы и просматриваете историю своего браузера. Не так уж и много, но все-таки раздражает.
Попытка пройти ссылки на моем веб-приложении работает правильно, но.
Настройка кэширования браузером не может быть выполнена.
Ответ 20
Для MVC это работает для меня:
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return Redirect(FormsAuthentication.GetRedirectUrl(User.Identity.Name, true));
}
Ответ 21
Я хотел добавить некоторую информацию, чтобы помочь понять проблему. Аутентификация форм позволяет хранить пользовательские данные либо в файле cookie, либо в строке запроса URL-адреса. Способ, поддерживаемый вашим сайтом, может быть настроен в файле web.config.
В соответствии с Microsoft:
Метод SignOut удаляет информацию о билетах формы-аутентификации из файла cookie или URL , если CookiesSupported является ложным.
В то же время говорят:
Одно из значений HttpCookieMode, которое указывает, приложение настроено для аутентификации без файлов cookie. The default - UseDeviceProfile.
Наконец, в отношении UseDeviceProfile, они говорят:
Если для свойства CookieMode установлено значение UseDeviceProfile, CookiesSupported возвращает true, если браузер для текущий запрос поддерживает как куки, так и перенаправление с помощью файлов cookie; в противном случае свойство CookiesSupported вернет false.
Соединяя это все вместе, в зависимости от пользовательского браузера, конфигурация по умолчанию может привести к тому, что CookiesSupported будет true, что означает, что метод SignOut не очищает билет от файла cookie. Это кажется противоречащим интуиции, и я не знаю, почему он работает таким образом. Я бы ожидал, что SignOut фактически подпишет пользователя при любых обстоятельствах.
Один из способов сделать работу SignOut сам по себе - изменить режим cookie на "UseCookies" (т.е. файлы cookie) в файле web.config:
<authentication mode="Forms">
<forms loginUrl="~/Account/SignIn" cookieless="UseCookies"/>
</authentication>
Согласно моим тестам, это делает SignOut самостоятельно, за счет вашего сайта, теперь требуется, чтобы файлы cookie функционировали правильно.
Ответ 22
Для меня работает следующий подход. Я думаю, что если после утверждения "FormsAuthentication.SignOut()" есть какая-либо ошибка, SingOut не работает.
public ActionResult SignOut()
{
if (Request.IsAuthenticated)
{
FormsAuthentication.SignOut();
return Redirect("~/");
}
return View();
}
Ответ 23
Помните, что WIF отказывается, чтобы сообщить браузеру об очистке файлов cookie, если сообщение wsignoutcleanup из STS не соответствует URL-адресу с именем приложения из IIS, и я имею в виду CASE SENSITIVE. WIF отвечает зеленой проверкой OK, но не отправляет команду для удаления файлов cookie в браузер.
Итак, вам нужно обратить внимание на чувствительность к регистру вашего URL.
Например, ThinkTecture Identity Server сохраняет URL-адреса посещаемых RP файлов в одном cookie файле, но делает их более строчными. WIF получит сообщение wsignoutcleanup в нижнем регистре и сравнит его с именем приложения в IIS. Если он не совпадает, он не удаляет файлы cookie, но будет сообщать об этом в браузер. Итак, для этого Identity Server мне нужно было написать все URL-адреса в файле web.config и всех именах приложений в IIS в нижнем регистре, чтобы избежать таких проблем.
Также не забудьте разрешить сторонние файлы cookie в браузере, если у вас есть приложения вне субдомена STS, иначе браузер не удалит файлы cookie, даже если WIF сообщает ему об этом.