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 сообщает ему об этом.