如何跨 HTTP 和 HTTPS 请求重用 SessionScope 的 JSF Beans?
How to reuse JSF Beans of SessionScope across HTTP and HTTPS requests?
考虑这个 index.xhtml 页面。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<f:view locale="en" encoding="UTF-8">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body class="ui-grid" id="body">
<h:form>
<h:commandButton value="Invalidate Session" action="#{loggedInUser.invalidateSession}"/>
</h:form>
</h:body>
</f:view>
</html>
还有这个 SessionScoped bean。
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@Named
@SessionScoped
public class LoggedInUser implements Serializable {
String user;
@PostConstruct
public void init() {
String remoteUser = this.user = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();
String sessionId = FacesContext.getCurrentInstance().getExternalContext().getSessionId(false);
System.out.println("Initializing. With SESSION ID " + sessionId);
System.out.println("Initializing. With remote user " + remoteUser);
}
public void invalidateSession() throws ServletException{
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
request.logout();
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
我在两个浏览器中访问该页面windows。
一个 Window (W1) 有 URL https://localhost:8181/pfdialogdemo/index.xhtml
另一个 Window (W2) 有 URL http://localhost:8080/pfdialogdemo/index.xhtml
这些是我执行的步骤。
- 在 W1 上单击 "Invalidate Session"。
- 重新加载 W1。
- 重新加载W2。
LoggedInUser.init()产生的输出;是
Information: Initializing. With SESSION ID b6d2858cc441c52540f54ee4cb0c
Information: Initializing. With remote user null
Information: Initializing. With SESSION ID b6d60472f8d5cca5b6feb5ff32d5
Information: Initializing. With remote user null
如果我愿意。
- 在 W2 上单击 "Invalidate Session"。
- 重新加载W2。
- 重新加载 W1。
输出是。
Information: Initializing. With SESSION ID b6de615078648aa44566af533a9f
Information: Initializing. With remote user null
为什么在第一个例子中第二次创建了SessionScoped bean?如何确保 SessionScoped bean 没有创建两次?为什么第二个例子只创建了一次?
此示例使用 Glassfish 4.1 和 JSF 2.2 (Mojarra)
这是符合预期的行为HTTP state (cookie) specification(即超出了 JSF 的控制范围)。
在 HTTPS 请求期间创建的 Cookie 不可用于同一 domain/path 上的 HTTP 请求。否则这将是一个安全漏洞,会破坏 HTTPS 的完整性和意义。只有反过来才有可能。
只需从 HTTP 永久重定向到 HTTPS,即可在您的 Web 应用程序上禁用 HTTP。
考虑这个 index.xhtml 页面。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<f:view locale="en" encoding="UTF-8">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body class="ui-grid" id="body">
<h:form>
<h:commandButton value="Invalidate Session" action="#{loggedInUser.invalidateSession}"/>
</h:form>
</h:body>
</f:view>
</html>
还有这个 SessionScoped bean。
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@Named
@SessionScoped
public class LoggedInUser implements Serializable {
String user;
@PostConstruct
public void init() {
String remoteUser = this.user = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();
String sessionId = FacesContext.getCurrentInstance().getExternalContext().getSessionId(false);
System.out.println("Initializing. With SESSION ID " + sessionId);
System.out.println("Initializing. With remote user " + remoteUser);
}
public void invalidateSession() throws ServletException{
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
request.logout();
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
我在两个浏览器中访问该页面windows。 一个 Window (W1) 有 URL https://localhost:8181/pfdialogdemo/index.xhtml 另一个 Window (W2) 有 URL http://localhost:8080/pfdialogdemo/index.xhtml
这些是我执行的步骤。
- 在 W1 上单击 "Invalidate Session"。
- 重新加载 W1。
- 重新加载W2。
LoggedInUser.init()产生的输出;是
Information: Initializing. With SESSION ID b6d2858cc441c52540f54ee4cb0c
Information: Initializing. With remote user null
Information: Initializing. With SESSION ID b6d60472f8d5cca5b6feb5ff32d5
Information: Initializing. With remote user null
如果我愿意。
- 在 W2 上单击 "Invalidate Session"。
- 重新加载W2。
- 重新加载 W1。
输出是。
Information: Initializing. With SESSION ID b6de615078648aa44566af533a9f
Information: Initializing. With remote user null
为什么在第一个例子中第二次创建了SessionScoped bean?如何确保 SessionScoped bean 没有创建两次?为什么第二个例子只创建了一次?
此示例使用 Glassfish 4.1 和 JSF 2.2 (Mojarra)
这是符合预期的行为HTTP state (cookie) specification(即超出了 JSF 的控制范围)。
在 HTTPS 请求期间创建的 Cookie 不可用于同一 domain/path 上的 HTTP 请求。否则这将是一个安全漏洞,会破坏 HTTPS 的完整性和意义。只有反过来才有可能。
只需从 HTTP 永久重定向到 HTTPS,即可在您的 Web 应用程序上禁用 HTTP。