【问题标题】:Strange problem with session.invalidate()session.invalidate() 的奇怪问题
【发布时间】:2010-09-04 18:52:56
【问题描述】:

我在登录和注销时遇到了奇怪的问题。我已经实现了基于容器的安全性。我的所有页面上都有登录/注销链接(通过template.xhtml),这些链接是否基于支持bean 布尔属性(实际上是方法isLoggedIn())呈现或不呈现。同样在支持 bean 中,我有方法注销,它是注销链接的操作(它是 h:commandLink)。注销方法返回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,反之亦然(我只想要 https 中的 login.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
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

现在我已成功登录,显示注销链接意味着支持 bean isLoggedIn 返回 true。现在我单击 Logout,它在 backing bean 的 logout() 方法中调用 session.invalidate():

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

过滤器再次将 index.xhtml 重定向到 http:

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

此时没有显示注销链接,是不是表示我们没有登录?作为响应,有 set-cookie,这是否意味着服务器将我注销?再次进入登录页面后,它从顶部开始。我还可以插入与正常登录和异常登录情况略有不同的服务器日志。还有关于 Expires 的回应,为什么是 1970 年 1 月?我真的很困惑。

【问题讨论】:

  • 在未来的 JSF/JSF 2.0 问题中,请标记为此类。 Java EE 是一个非常广泛的主题。 JSF 只是其中的一小部分。使用标签可以吸引更好的受众,因为这里的人们经常通过标签浏览问题。

标签: java session jsf jsf-2 logout


【解决方案1】:

由于在使用容器管理的安全性时,您不应该在不登录的情况下访问受限页面,因此我强烈怀疑 isLoggedIn() 方法错误地返回了 false,这使得它看起来像说明您尚未登录。该方法至少应如下所示:

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

更新:是的,当在 HTTPS 上下文中创建 cookie(即具有 Secure 标志)时,从 HTTPS 切换到 HTTP 时 cookie 会丢失。但是,如果 cookie 是在 HTTP 上下文中创建的(即没有 Secure 标志),那么 cookie 将在 HTTP 和 HTTPS 上下文中保持可用。这是根据RFC 2965 cookie 规范(检查Secure 标志的描述)。

除了使用HttpServletRequest#logout(),另一种解决方案是在注销后重定向期间立即创建cookie,而不是仅在通过HTTPS 请求登录页面时创建cookie。你可以通过请求HttpSession来隐式创建一个新的cookie

【讨论】:

  • 我已经用 isLoggedIn 实现更新了我的问题。顺便问一下你好:)
  • 好吧,虽然有点过于复杂,但您的 isLoggedIn() 看起来不错。您使用的是什么 servlet 容器?登录后按F5显示未登录怎么办?请求/响应标头说什么?我至少以前没有见过这个问题,如果没有关于配置/环境的更多细节,很难尝试复制同样的问题。
  • F5 没有帮助。我正在使用 glassfish v3。它抛出一些异常:INFO:JACC 策略提供者:权限检查失败,上下文(blog/blog-war_war)-权限((javax.security.jacc.WebUserDataPermission /ssl/login.xhtml GET))最好:JACC 策略提供者:PolicyWrapper .getPermissions(d), context (blog/blog-war_war) 权限:java.security.Permissions@1ef29515 (...我认为这是因为我在 web.xml 中为 /ssl/* 指定了安全约束 SSL 区域 (登录页面在 /ssl/login.xhtml 下),我没有 但我有 CONFIDENTIAL.
  • 如果你愿意,我可以粘贴日志。以及如何检查这些标题?打印出来?
  • 您可以使用 FireBug 或 Fiddler 检查标头。注意会话 cookie 和身份验证标头的设置/发送方式的差异。
【解决方案2】:

如果您使用 session.invalidate(),isLoggedIn() 的正确测试是 userPrincipal() != null && session.isRequestedSessionValid()。否则,退出后的页面将显示您仍处于登录状态。

您不应该自己重定向到登录页面。 CMA 应该为您做到这一点。只需重定向到需要登录的页面。

【讨论】:

    猜你喜欢
    • 2015-02-27
    • 2018-06-26
    • 2011-08-13
    • 2011-08-17
    • 2011-02-02
    • 2021-10-10
    • 2014-04-21
    • 2010-12-30
    • 2014-03-21
    相关资源
    最近更新 更多