FormsAuthentication.SignOut () не выходит из системы - PullRequest
139 голосов
/ 05 января 2009

Слишком долго разбил мне голову об этом. Как запретить пользователю просматривать страницы сайта после того, как они вышли из системы с помощью FormsAuthentication.SignOut? Я ожидал бы, что это сделает это:

FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();

Но это не так. Если я введу URL-адрес напрямую, я все равно смогу перейти на страницу. Я давно не пользуюсь защитой по собственной инициативе, поэтому забываю, почему это не работает.

Ответы [ 23 ]

198 голосов
/ 20 августа 2009

Пользователи по-прежнему могут просматривать ваш веб-сайт, поскольку файлы 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 .

20 голосов
/ 05 января 2009

Похоже, у вас не правильно настроен раздел авторизации web.config. Ниже приведен пример.

<authentication mode="Forms">
  <forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
  <deny users="?" />
</authorization>
20 голосов
/ 15 февраля 2012

Используя две из вышеперечисленных публикаций x64igor и Phil Haselden, решил это:

1. x64igor привел пример выхода из системы:

  • Сначала необходимо Очистить файл 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" ); 
    }
    
12 голосов
/ 22 марта 2010

Ключевым моментом здесь является то, что вы говорите: «Если я введу URL-адрес напрямую ...».

По умолчанию при проверке подлинности с помощью форм браузер кэширует страницы для пользователя. Поэтому, выбирая URL-адрес непосредственно из раскрывающегося списка адресов браузера или вводя его, МОЖЕТ получить страницу из кэша браузера и никогда не возвращаться на сервер для проверки аутентификации / авторизации. Решением этой проблемы является предотвращение кэширования на стороне клиента в событии Page_Load каждой страницы или в OnLoad () вашей базовой страницы:

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Вы также можете позвонить:

Response.Cache.SetNoStore();
11 голосов
/ 28 мая 2010

Я тоже с этим раньше боролся.

Вот аналогия с тем, что, похоже, происходит ... Новый посетитель, Джо, заходит на сайт и входит через страницу входа с помощью FormsAuthentication. ASP.NET генерирует новую личность для Джо и дает ему cookie. Это печенье похоже на ключ от дома, и пока Джо возвращается с этим ключом, он может открыть замок. Каждому посетителю предоставляется новый ключ и новый замок для использования.

Когда вызывается FormsAuthentication.SignOut(), система говорит Джо потерять ключ. Обычно это работает, поскольку у Джо больше нет ключа, он не может войти.

Однако, если Джо когда-нибудь вернется, и у есть тот потерянный ключ, его снова впускают!

Из того, что я могу сказать, нет способа заставить ASP.NET изменить замок на двери!

Я могу жить с этим, запоминая имя Джо в переменной Session. Когда он выходит из системы, я прекращаю сеанс, поэтому у меня больше нет его имени. Позже, чтобы проверить, разрешен ли ему вход, я просто сравниваю его Identity.Name с тем, что имеет текущий сеанс, и если они не совпадают, он не является действительным посетителем.

Короче говоря, для веб-сайта НЕ полагайтесь на User.Identity.IsAuthenticated, не проверяя также переменные Session!

6 голосов
/ 28 августа 2015

После долгих поисков, наконец, это сработало для меня. Надеюсь, это поможет.

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>
6 голосов
/ 26 мая 2011

Это работает для меня

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());
    }
3 голосов
/ 06 мая 2009

Я писал базовый класс для всех своих страниц и столкнулся с той же проблемой. У меня был код, подобный следующему, и он не работал. При трассировке управление переходит от оператора 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 () не является проблемой, метод перенаправления - один.

Я надеюсь, что это может помочь кому-то

Привет

3 голосов
/ 27 декабря 2016

Этот ответ технически идентичен Хосро.Пакманеш. Я публикую его, чтобы уточнить, чем его ответ отличается от других ответов в этой теме, и в каком случае его можно использовать.

В общем, чтобы очистить пользовательский сеанс, сделав

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.

3 голосов
/ 05 января 2009

Код, который вы разместили, выглядит так, как будто он должен правильно удалить маркер аутентификации форм, поэтому вполне возможно, что рассматриваемые папки / страницы фактически не защищены.

Подтвердили ли вы, что доступ к страницам невозможен до того, как произойдет вход в систему?

Можете ли вы опубликовать настройки web.config и код входа в систему, который вы используете?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...