Файл cookie проверки подлинности форм и проверки подлинности не сохраняется - PullRequest
1 голос
/ 18 января 2011

знаю, что есть много вопросов, связанных с проверкой подлинности с помощью форм и сохранением файлов cookie, но, потратив большую часть дня на изучение, я все еще испытываю трудности.

Моя проблема

Я работаю над веб-приложением (VS2010, но webapp - версия 3.5), которое ограничивает доступ к определенным частям приложения для аутентифицированных пользователей (тогда как другие части открыты).Моя проблема в том, что мои куки-файлы аутентификации не сохраняются после закрытия браузера.

Мой подход

Я написал простую страницу login.aspx, которая настроена в web.config следующим образом:

<authentication mode="Forms">

... и поведение отдельных страниц объявляется так:

<location path="ClientManageAccount.aspx">
     <system.web>
        <authorization>
           <deny users="?" />
        </authorization>
     </system.web>
</location>

..., который прекрасно работает во всех отношениях, КРОМЕ этого феномена cookie ...

Я создаю куки-файл аутентификации вручную, как только я аутентифицировал логин и пароль моего пользователя по базе данных (которая отлично работает) на странице login.aspx.Если пользователь установит флажок «держать меня в системе», файл cookie будет создан с использованием этого метода:

    private void GenerateAuthenticationCookie(int expiryInMinutes, Guid userGuid)
    {
        DateTime cookieExpiration = DateTime.Now.AddMinutes(expiryInMinutes); // change to months for production
        var authenticationTicket =
            new FormsAuthenticationTicket(
                2,
                userGuid.ToString(), 
                DateTime.Now,
                cookieExpiration,
                true, 
                string.Empty,
                FormsAuthentication.FormsCookiePath);

        // ticket must be encrypted
        string encryptedTicket = FormsAuthentication.Encrypt(authenticationTicket);

        // create cookie to contain encrypted auth ticket
        var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
        authCookie.Expires = authenticationTicket.Expiration;
        authCookie.Path = FormsAuthentication.FormsCookiePath;

        // clear out existing cookie for good measure (probably overkill) then add
        HttpContext.Current.Response.Cookies.Remove(FormsAuthentication.FormsCookieName); 
        HttpContext.Current.Response.Cookies.Add(authCookie);
    }

Цель состоит в том, чтобы сохранить Guid пользователя в файле cookie авторизации, который я затем буду использоватьвосстановить объект пользователя в сеансе (это также на странице login.aspx, и я думаю, что я хотел бы извлечь guid пользователя из созданного мной файла cookie auth и использовать его для заполнения соответствующей записи пользователяв сеанс и перенаправьте на запрошенную страницу):

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            TryAutoLogin();
        }            
    }

    private void TryAutoLogin()
    {
        HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);

        if (cookie != null)
        {
            FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);

            if (ticket != null)
            {
                if (ticket.Name.Length > 0)
                {
                    try
                    {
                        Guid userGuid = new Guid(ticket.Name);
                        KUser user = UserFunctions.GetUserFromUserGuid(userGuid);

                        if (user != null) Session["User"] = user;

                        FormsAuthentication.RedirectFromLoginPage(userGuid.ToString(), true);
                    }
                    catch (Exception anyException)
                    {
                        // don't do anything for now - do something smart later :-)                        }
                }
            }
        }
    }

Наконец, вот код кнопки входа в систему на моей странице login.aspx:

    protected void Submit_OnClick(object sender, EventArgs e)
    {
        long userId = 0;
        UserAuthenticationStatus status;

        status = (UserAuthenticationStatus)UserFunctions.UserAuthenticates(EmailAddress.Text, Password.Text, ref userId);

        switch (status)
        {
            case UserAuthenticationStatus.Authenticated:
                //email address and password match, account ok, so log this user in
                KUser user = UserFunctions.GetUser(userId);
                Session["User"] = user;

                if (ChkRememberMe.Checked)
                {
                    GenerateAuthenticationCookie(15, user.UserGuid); // 15 minutes

                    FormsAuthentication.RedirectFromLoginPage(user.UserGuid.ToString(), true);
                }
                else
                {
                    FormsAuthentication.RedirectFromLoginPage(user.UserGuid.ToString(), false);
                }
                break;
            case UserAuthenticationStatus.AuthButLocked:
                // email/pwd match but account is locked so do something
                ShowLockedAccountMessage();
                break;
            case UserAuthenticationStatus.EmailFoundIncorrectPassword:
            case UserAuthenticationStatus.EmailNotFound:
            case UserAuthenticationStatus.Unknown:
                // either the email wasn't found, or the password was incorrect or there was some other problem
                // present message stating this and offer chance to register
                ShowFailedLoginMessage();
                break;
            default:
                ShowUnavailableMessage();
                break;
        }
    }

Как видите,в этом нет ничего особенно сложного, но несмотря на то, что authCookie, созданный в GenerateAuthenticationCookie (..), создается правильно (насколько я могу судить), он не сохраняется.

Одна вещь, которую я заметилявляется то, что, если я помещаю некоторый код в метод Application_AuthenticateRequest в global.asax.cs, например:

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);

        if (cookie != null)
        {
            int x = 4;  // just a dummy line so that I can set a breakpoint
        }
    }

... эта точка остановаколичество попаданий после нового сеанса браузера, хотя оно перестает срабатывать, как только я ухожу со страницы запуска (в данном случае фиктивная страница start.aspx, используемая исключительно для разработки и тестирования).

Итак, извинения за длинный вопрос, но я действительно страдаю здесь.

Вещи, которые я проверял / пробовал

Обеспечение выполнения кода - ДАНастройки браузера - т.е. нет удаления файлов cookie при выходе - ПОДТВЕРЖДЕНО, НЕТ УДАЛЕНИЯ Попытка использовать разные тайм-ауты - например, они равны или отличаются от таймаута web.config, кажется, не имеет значения ... ... и, конечно, по крайней мере двадцать или тридцать разныхпредыдущие вопросы, но безрезультатно.

System / Dev Environment

Windows 7 64-bit, VS2010 (но proj is 3.5), SQL Server 2008 Express.

На моем dev-сервере эта проблема остается, поэтому я не уверен, что она обязательно является экологической - эта машина является блоком WS2008R2, на котором выполняется SQL 2008R2 - и та же проблема остается.

Кто-нибудь, кто-нибудь, когда-нибудьу вас есть идеи, что я могу попробовать здесь?У меня есть предчувствие, что я мог бы заставить это работать, перехватывая начальный удар Application_AuthenticateRequest в global.asax.cs и вставляя что-то в состояние сеанса, чтобы пометить его как «authenticated» (чтобы избежать дорогостоящей попытки аутентификации каждый раз, когда вызывается этот метод, что оказываетсябыть несколько раз на странице.

Заранее спасибо,

Джон

1 Ответ

3 голосов
/ 18 января 2011

ОК, потратив все это время на написание этого, у меня был момент ясности и я понял, что (а) мне не нужно было выполнять какую-либо из этих проверок в Page_Load (), как (если бы это работало должным образом)страница login.aspx вообще не будет вызываться, и (б) я должен был получить доступ к cookie из Session_Start - именно туда я переместил код TryAutoLogin.

Это само по себеЭто был шаг вперед, но, несмотря на получение cookie-файла и, следовательно, на него пользователя, я обнаружил, что по-прежнему возвращаюсь к странице login.aspx.

Именно в этот момент я вспомнил тот факт,что у меня есть родительская главная страница и две дочерние главные страницы - одну, которую я установил для страниц без аутентификации (например, домашней страницы) и одну для тех страниц, которые требуют аутентификации.Я смутно вспомнил проблему с тайм-аутами сеанса и поместил следующий код в переопределение OnInit:

       if (Session["User"] == null)
       {
              FormsAuthentication.SignOut();
              FormsAuthentication.RedirectToLoginPage();
              Response.End();
       }

..., что само по себе было не так уж плохо (и избежало неприятной ошибки при тайм-аутах), но такжена странице start.aspx я нашел этот драгоценный камень:

Session.Clear();

... в Page_Load!

Итак, я случайно очистил сеанс, в который яразместил мою недавно восстановленную запись пользователя.Это означало, что переопределение OnInit главной страницы авторизации затем обнаруживало отсутствие объекта пользователя и - та, да!- выход пользователя из системы, который, в свою очередь, удаляет файл авторизации ...

Итак, немного проводки и чуть позже, и я могу уложить ее в кровать.

Спасибо зачтение (даже если бы я понял это сам) ...:)

...