Странная проблема с session.invalidate()

У меня странная проблема со входом и выходом. Я реализовал безопасность на основе контейнеров. У меня есть ссылки входа/выхода на всех моих страницах (через template.xhtml), которые отображаются или не основаны на логическом свойстве поддерживающего компонента (на самом деле это метод isLoggedIn()). Также в компоненте поддержки у меня есть метод выхода из системы, который является действием для ссылки выхода (это h:commandLink). Метод Logout возвращает String, который перенаправляет на страницу входа через неявную навигацию JSF 2.0. Теперь, когда я развертываю приложение, я перехожу на свою страницу, она отображает index.xhtml. Оттуда я перехожу на страницу входа. Я ввожу свое имя пользователя/пароль, нажимаю «Войти», и он входит в систему. Но теперь я нажимаю «Выход», который вызывает упомянутый метод выхода из системы поддержки bean, который вызывает это:

public String logout() {
    HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
   //HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
   try {
       session.invalidate();
       //request.logout();
   } catch (Exception ex) {
       Logger.getLogger(PostController.class.getName()).log(Level.SEVERE, null, ex);
   }
   return "/ssl/login?faces-redirect=true";
}

Теперь после нажатия «Выйти» он перенаправляет меня обратно на страницу входа, когда я снова ввожу имя пользователя/пароль и нажимаю «Войти». Но затем происходит странная вещь, потому что он отображает мне мой index.xhtml, но я не вошел в систему. Мне нужно снова перейти на страницу входа в систему, повторно ввести учетные данные еще раз, чтобы, наконец, войти в систему. Это происходит только тогда, когда я использую session.invalidate() в методе поддержки bean-компонента logout() . Когда я использую request.logout(), все работает нормально. В чем проблема?

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

public boolean isLoggedIn() {
    HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
    if(request.getUserPrincipal() != null)
        return true;
    else
        return false;
}

Отредактировано: вот сценарий с учетом заголовков http: я запрашиваю login.xhtml:

GET /blog-war/ssl/login.xhtml;jsessionid=edccb9f9a1c5fc77dbd7fc86f55b HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost:8080/blog-war/
Cookie: JSESSIONID=edccb9f9a1c5fc77dbd7fc86f55b

Ответ:

HTTP/1.1 302 Moved Temporarily
X-Powered-By: Servlet/3.0
Server: GlassFish Server Open Source Edition 3.0.1
Location: https://localhost:8181/blog-war/ssl/login.xhtml
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-GB
Content-Length: 197
Date: Sat, 04 Sep 2010 22:27:47 GMT

Временно перемещено, поэтому браузер делает еще один запрос:

GET /blog-war/ssl/login.xhtml HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost:8080/blog-war/
Cookie: JSESSIONID=edccb9f9a1c5fc77dbd7fc86f55b

Ответ:

HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0, JSF/2.0
Server: GlassFish Server Open Source Edition 3.0.1
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Type: text/html;charset=UTF-8
Content-Length: 1256
Date: Sat, 04 Sep 2010 22:27:47 GMT

Я заполняю имя пользователя/пароль и нажимаю Войти:

POST /blog-war/ssl/j_security_check HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: https://localhost:8181/blog-war/ssl/login.xhtml
Cookie: JSESSIONID=edccb9f9a1c5fc77dbd7fc86f55b

Ответ:

HTTP/1.1 302 Moved Temporarily
X-Powered-By: Servlet/3.0
Server: GlassFish Server Open Source Edition 3.0.1
Location: https://localhost:8181/blog-war/
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-GB
Content-Length: 182
Date: Sat, 04 Sep 2010 22:40:01 GMT

Это было перенаправлено на index.xhtml:

GET /blog-war/ HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: https://localhost:8181/blog-war/ssl/login.xhtml
Cookie: JSESSIONID=edccb9f9a1c5fc77dbd7fc86f55b

Ответ:

HTTP/1.1 302 Moved Temporarily
X-Powered-By: Servlet/3.0
Server: GlassFish Server Open Source Edition 3.0.1
Pragma: No-cache
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 01:00:00 CET
Location: http://localhost:8080/blog-war/
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-GB
Content-Length: 181
Date: Sat, 04 Sep 2010 22:40:01 GMT

Снова перенаправление, потому что у меня есть фильтр, который переключается на https-http и наоборот (я хотел только login.xhtml в https):

GET /blog-war/ HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: JSESSIONID=edccb9f9a1c5fc77dbd7fc86f55b

Ответ:

HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0, JSF/2.0
Server: GlassFish Server Open Source Edition 3.0.1
Pragma: no-cache
Cache-Control: no-cache, no-store, must-revalidate
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Type: text/html;charset=UTF-8
Content-Length: 4002
Date: Sat, 04 Sep 2010 22:40:02 GMT

Теперь я успешно вошел в систему, ссылка Logout отображается, значит, вспомогательный компонент isLoggedIn возвращает true. Теперь я нажимаю Logout, который вызывает session.invalidate() в методе logout() в компоненте поддержки:

POST /blog-war/index.xhtml HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost:8080/blog-war/
Cookie: JSESSIONID=edccb9f9a1c5fc77dbd7fc86f55b

Ответ:

HTTP/1.1 302 Moved Temporarily
X-Powered-By: Servlet/3.0, JSF/2.0
Server: GlassFish Server Open Source Edition 3.0.1
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Location: http://localhost:8080/blog-war/ssl/login.xhtml
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-GB
Content-Length: 196
Date: Sat, 04 Sep 2010 22:48:34 GMT

Перенаправление на страницу входа в систему возвращает строку «/ssl/login?faces-redirect=true», поэтому мы идем туда:

GET /blog-war/ssl/login.xhtml HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost:8080/blog-war/
Cookie: JSESSIONID=edccb9f9a1c5fc77dbd7fc86f55b

Ответ:

HTTP/1.1 302 Moved Temporarily
X-Powered-By: Servlet/3.0
Server: GlassFish Server Open Source Edition 3.0.1
Location: https://localhost:8181/blog-war/ssl/login.xhtml
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-GB
Content-Length: 197
Date: Sat, 04 Sep 2010 22:48:34 GMT

Другой редирект, страница входа должна быть в https (фильтр работает :)):

GET /blog-war/ssl/login.xhtml HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost:8080/blog-war/
Cookie: JSESSIONID=edccb9f9a1c5fc77dbd7fc86f55b

Ответ:

HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0, JSF/2.0
Server: GlassFish Server Open Source Edition 3.0.1
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: JSESSIONID=eefdcda45337b9c897de2a0e95e3; Path=/blog-war; Secure
Content-Type: text/html;charset=UTF-8
Content-Length: 1256
Date: Sat, 04 Sep 2010 22:48:35 GMT

Так что это был нормальный ход событий. Теперь ненормально :) Я уже на странице входа в систему, поэтому я повторно ввожу имя пользователя/пароль и нажимаю Войти:

POST /blog-war/ssl/j_security_check HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: https://localhost:8181/blog-war/ssl/login.xhtml
Cookie: JSESSIONID=eefdcda45337b9c897de2a0e95e3

Ответ:

HTTP/1.1 302 Moved Temporarily
X-Powered-By: Servlet/3.0
Server: GlassFish Server Open Source Edition 3.0.1
Location: https://localhost:8181/blog-war/
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-GB
Content-Length: 182
Date: Sat, 04 Sep 2010 22:55:46 GMT

Перенаправить на индекс:

GET /blog-war/ HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: https://localhost:8181/blog-war/ssl/login.xhtml
Cookie: JSESSIONID=eefdcda45337b9c897de2a0e95e3

Ответ:

HTTP/1.1 302 Moved Temporarily
X-Powered-By: Servlet/3.0
Server: GlassFish Server Open Source Edition 3.0.1
Pragma: No-cache
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 01:00:00 CET
Location: http://localhost:8080/blog-war/
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-GB
Content-Length: 181
Date: Sat, 04 Sep 2010 22:55:47 GMT

Снова фильтр перенаправляет на http для index.xhtml:

GET /blog-war/ HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive

Ответ:

HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0, JSF/2.0
Server: GlassFish Server Open Source Edition 3.0.1
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: JSESSIONID=ef675cbb9747063c235fdb44137e; Path=/blog-war
Content-Type: text/html;charset=UTF-8
Content-Length: 3410
Date: Sat, 04 Sep 2010 22:55:48 GMT

На данный момент ссылка Logout не отображается, значит, мы не вошли в систему? В ответ есть set-cookie, значит ли это, что сервер меня разлогинил? После повторного перехода на страницу входа все начинается сначала. Я также могу вставить журналы сервера, которые немного отличаются от обычного входа в систему и ненормального сценария входа в систему. Тоже про Expires в ответ, почему сейчас январь 1970? Я действительно смущен.


person l245c4l    schedule 04.09.2010    source источник
comment
В будущих вопросах по JSF/JSF 2.0 отмечайте их как таковые. Java EE — очень обширная тема. JSF — лишь его маргинальная часть. С тегами вы достигаете лучшей аудитории, так как люди здесь часто просматривают вопросы по тегам.   -  person BalusC    schedule 04.09.2010


Ответы (2)


Поскольку вы не сможете получить доступ к страницам с ограниченным доступом без входа в систему при использовании безопасности, управляемой контейнером, я сильно подозреваю, что метод isLoggedIn() неправильно вернул false, из-за чего выглядело, что вы не вошли в систему. , Метод должен выглядеть как минимум так:

public boolean isLoggedIn() {
    return FacesContext.getCurrentInstance()
        .getExternalContext().getUserPrincipal() != null;
}

Обновление: верно, когда файл cookie создается в контексте HTTPS (т. е. имеет флаг Secure), то файл cookie теряется при переключении с HTTPS на HTTP. Однако, если файл cookie был создан в контексте HTTP (т. е. не имеет флага Secure), то файл cookie останется доступным как в контексте HTTP, так и в контексте HTTPS. Это соответствует спецификации файла cookie RFC 2965 (см. описание флага Secure).

Помимо использования HttpServletRequest#logout(), другим решением было бы создание файла cookie сразу во время перенаправления после выхода из системы, а не только тогда, когда страница входа запрашивается через HTTPS. Вы можете неявно создать новый файл cookie, просто запросив HttpSession

person BalusC    schedule 04.09.2010
comment
Я обновил свой вопрос реализацией isLoggedIn. ТС привет еще раз :) - person l245c4l; 04.09.2010
comment
Что ж, хотя ваш isLoggedIn() немного усложнен, он выглядит нормально. Какой сервлетконтейнер вы используете? Что происходит, когда вы нажимаете F5 после входа в систему, которая показывает, что вы не вошли в систему? Что говорят заголовки запроса/ответа? По крайней мере, я раньше не сталкивался с этой проблемой, и трудно попытаться воспроизвести ту же проблему без более подробной информации о конфигурациях/среде. - person BalusC; 04.09.2010
comment
F5 не помогает. Я использую стеклянную рыбу v3. Он выдает некоторое исключение: ИНФОРМАЦИЯ: Поставщик политики JACC: Ошибка проверки разрешений, контекст (блог/блог-война_войны) - разрешение ((javax.security.jacc.WebUserDataPermission /ssl/login.xhtml GET)) FINEST: Поставщик политики JACC: PolicyWrapper .getPermissions(d), разрешения контекста (blog/blog-war_war): java.security.Permissions@1ef29515 (... И я думаю, это потому, что я указал область SSL с ограничением безопасности в web.xml для /ssl/* ( страница входа находится в /ssl/login.xhtml), и у меня нет ‹auth-constraint›, но у меня есть ‹user-data-constraint› КОНФИДЕНЦИАЛЬНО. - person l245c4l; 04.09.2010
comment
Я могу вставить логи, если хотите. И как проверить эти заголовки? Просто распечатать? - person l245c4l; 04.09.2010
comment
Вы можете проверить заголовки с помощью FireBug или Fiddler. Следите за различиями в том, как файлы cookie сеанса и заголовки аутентификации устанавливаются/отправляются. - person BalusC; 05.09.2010
comment
Я действительно хочу понять, как все работает. Когда я перенаправляюсь на страницу входа в систему после выхода из системы, он создает файл cookie «слишком поздно», когда я уже нахожусь в канале ssl. Затем, когда я перезахожу, что на самом деле происходит за кулисами. Из журналов я вижу, что сервер регистрирует меня, но затем я перенаправляюсь на http и сервер выходит из системы? Когда сервер решает отправить мне новый файл cookie, и при отправке он выходит из системы. Или я все еще вошел в систему, но браузер использует cookie с другим идентификатором, поэтому сервер распознает меня как другого пользователя? Мне просто интересно, что сервер делает :) - person l245c4l; 05.09.2010

Если вы используете session.invalidate(), правильным тестом для isLoggedIn() будет userPrincipal() != null && session.isRequestedSessionValid(). В противном случае страница сразу после выхода будет показывать, что вы вошли в систему.

Вы не должны сами перенаправлять на страницу входа. CMA должен сделать это за вас. Просто перенаправьте на страницу, которая требует авторизации.

person user207421    schedule 05.09.2010