JSF / primefaces 会话 - 会话丢失
JSF / primefaces Session - Session gets lost
我是 JSF 编程新手,我的 login/session 出现问题,登录后丢失。
我想实现一个简单的登录,用户可以在其中输入用户名和密码。所以我写了一个LoginController:
@ManagedBean
@SessionScoped
public class LoginController extends AbstractController{
@PostConstruct
public void initialiseSession() {
FacesContext.getCurrentInstance().getExternalContext().getSession(true);
}
private String username = "null";
private String password;
private boolean loggedIn = false;
@Inject
private EmployeeService employeeService;
public static final String employeeSessionKey = "user";
public LoginController() {
}
public String login() {
//check username and password and if true redirect to "/"
}
我的 login.xhtml 看起来像:
<h:form id="loginForm">
<h:outputLabel style="font-size:24px" value="Bitte melden Sie sich an!"/>
<p:panelGrid columns="2">
<p:outputLabel id="userOutput" for="userInput" value="Benutzername"/>
<p:inputText id="userInput" value="#{loginController.username}"></p:inputText>
<p:outputLabel id="passwordOutput" for="passwordInput" value="Passwort"/>
<p:inputText id="passwordInput" type="password" value="#{loginController.password}"></p:inputText>
<h:outputText value="Logindaten merken?" id="outputRememberLogin">
<p:selectBooleanCheckbox id="loginCheckbox">
</p:selectBooleanCheckbox>
<p:spacer width="10" id="loginFormLittleSpacer"></p:spacer>
</h:outputText>
<p:commandButton id="loginButton" value="Anmelden" action="#{loginController.login()}" ajax="false" >
</p:commandButton>
</p:panelGrid>
</h:form>
因此,当我登录时,重定向有效。但是当我转到另一个 .xhtml 页面时,会话丢失了。
为了测试这一点,我输入了
<p:outputLabel value="#{loginController.username}"/>
在我的页面上。登录后,用户名变为"null"。
我对这个问题很着迷。
有什么想法吗?
先谢谢了。
您的 LoginController
bean 看起来它的注释没问题,代码看起来应该可以工作。但是,您可能还需要检查其他几件事。其中一些可能是显而易见的,但您的问题缺少一些细节,因此我不确定您可能拥有什么水平的经验以及从哪里开始回答这个问题。因此,我从头开始(差不多)…
1.域名配置
要使用会话,您必须使用合格的域名。向 IP 地址发送请求将不允许会话工作,因为客户端浏览器仅将会话信息发送到完全限定的域名 (http://example.com/). If you’re calling your web app with an IP (such as ‘http://127.0.0.1:8080/MyApp’), the session data will never be sent to your web app and you will have a new session created with each request. Make sure you’re using a fully qualified domain name and path with each request to your application, for example ‘http://localhost:8080/MyApp'。
2。应用配置
检查您的 Web 应用程序的 <session-config>
配置是否设置正确。默认配置应该允许您的代码在无需添加任何特定内容的情况下工作,所以如果您没有添加任何内容,请不要担心这一点。但是,您可能想要确保没有任何东西可以阻止会话被重用。
- 应启用会话 cookie (
<tracking-mode>COOKIE</tracking-mode>
)
- 超时应足够长,以便在第二次请求之前不会过期 (
<session-timeout>60</session-timeout>
)
- 应正确设置 cookie 路径以供您使用 (
<path>/</path>
)
以下是我常用的会话配置…
<session-config>
<session-timeout>60</session-timeout>
<tracking-mode>COOKIE</tracking-mode>
<cookie-config>
<path>/</path>
<http-only>true</http-only>
<secure>false</secure>
</cookie-config>
</session-config>
3。客户端会话 Cookie 跟踪
如果以上几点不能解决问题,您可以通过监控您的应用程序和客户端浏览器之间的请求和响应流量来真正开始深入研究会话跟踪。会话信息由名为“JSESSIONID”的 cookie(如果禁用 cookie 则为查询字符串参数)来回传递。它的值将是唯一会话的 ID,并且每个请求都必须相同,以确保您的 Web 应用程序跟踪相同的会话。下面重点介绍了一些需要寻找的东西……
确保“JSESSIONID”会话 cookie 已正确发送到客户端浏览器,并随每个后续请求一起发回。您可以使用 Chrome 或 Safari 的网络开发工具(在 'Network' 选项卡下)或使用单独的实用程序(例如 Wireshark)来完成此操作。
- 确保 'JSESSIONID' cookie 存在于第一个请求的响应中……这会让您知道您的网络应用程序至少正在创建会话和响应 cookie。
- 确保来自客户端浏览器的第二个请求将 'JSESSIONID' cookie 传回...这是您的网络应用知道要使用哪个现有会话的唯一方法。
- 确保 'JESSIONID' cookie 的路径为“/”(在浏览器中可能显示为 'N/A')或您的网络应用程序的路径(例如“/MyApp” )… 客户端浏览器只会将 cookie 发送到与每个域关联的域和路径。例如,如果您的登录页面是“http://example.com/MyApp/login', the 'JSESSIONID' cookie may have a path of '/MyApp' (by default), which will not be returned if the following request is made to 'http://example.com/”(没有“/MyApp”路径)。默认路径是您的网络应用程序的名称(“/MyApp”),可以使用上面指示的
<path>
配置项进行更改。
4. Bean 中的会话管理(附加信息)
在您的 initialiseSession()
方法中,FacesContext.getCurrentInstance().getExternalContext().getSession(true);
返回的会话对象没有被保存,这一行实际上什么也没做。在调用 initialiseSession()
之前,@SessionScoped
注释将已经创建了一个会话并将“JSESSIONID”cookie 添加到响应中。因此,调用 getSession(true)
的唯一原因是如果您想将会话保存到 bean 中的私有对象,就像这样...
@ManagedBean
@SessionScoped
public class LoginController extends AbstractController{
// Create a global, private member for storing the session data...
private HttpSession session;
@PostConstruct
public void initialiseSession() {
// Assign the session to the global member…
session = FacesContext.getCurrentInstance().getExternalContext().getSession(true);
}
…
同样,在您的示例中不需要调用 getSession(true)
,因为 SessionScoped
bean 已经创建了会话。仅当您打算更新或使用会话对象时才需要上述代码,例如添加属性或修改设置。
总结
仔细检查以上第 1 - 3 点。我的假设是“JSESSIONID”cookie 不会在后续请求中发回。如果您可以确认每个请求中都包含“JSESSIONID”cookie(具有相同的值),那么问题与会话无关,可能与您的 login()
方法中的代码有关。
我是 JSF 编程新手,我的 login/session 出现问题,登录后丢失。
我想实现一个简单的登录,用户可以在其中输入用户名和密码。所以我写了一个LoginController:
@ManagedBean
@SessionScoped
public class LoginController extends AbstractController{
@PostConstruct
public void initialiseSession() {
FacesContext.getCurrentInstance().getExternalContext().getSession(true);
}
private String username = "null";
private String password;
private boolean loggedIn = false;
@Inject
private EmployeeService employeeService;
public static final String employeeSessionKey = "user";
public LoginController() {
}
public String login() {
//check username and password and if true redirect to "/"
}
我的 login.xhtml 看起来像:
<h:form id="loginForm">
<h:outputLabel style="font-size:24px" value="Bitte melden Sie sich an!"/>
<p:panelGrid columns="2">
<p:outputLabel id="userOutput" for="userInput" value="Benutzername"/>
<p:inputText id="userInput" value="#{loginController.username}"></p:inputText>
<p:outputLabel id="passwordOutput" for="passwordInput" value="Passwort"/>
<p:inputText id="passwordInput" type="password" value="#{loginController.password}"></p:inputText>
<h:outputText value="Logindaten merken?" id="outputRememberLogin">
<p:selectBooleanCheckbox id="loginCheckbox">
</p:selectBooleanCheckbox>
<p:spacer width="10" id="loginFormLittleSpacer"></p:spacer>
</h:outputText>
<p:commandButton id="loginButton" value="Anmelden" action="#{loginController.login()}" ajax="false" >
</p:commandButton>
</p:panelGrid>
</h:form>
因此,当我登录时,重定向有效。但是当我转到另一个 .xhtml 页面时,会话丢失了。
为了测试这一点,我输入了
<p:outputLabel value="#{loginController.username}"/>
在我的页面上。登录后,用户名变为"null"。
我对这个问题很着迷。
有什么想法吗?
先谢谢了。
您的 LoginController
bean 看起来它的注释没问题,代码看起来应该可以工作。但是,您可能还需要检查其他几件事。其中一些可能是显而易见的,但您的问题缺少一些细节,因此我不确定您可能拥有什么水平的经验以及从哪里开始回答这个问题。因此,我从头开始(差不多)…
1.域名配置
要使用会话,您必须使用合格的域名。向 IP 地址发送请求将不允许会话工作,因为客户端浏览器仅将会话信息发送到完全限定的域名 (http://example.com/). If you’re calling your web app with an IP (such as ‘http://127.0.0.1:8080/MyApp’), the session data will never be sent to your web app and you will have a new session created with each request. Make sure you’re using a fully qualified domain name and path with each request to your application, for example ‘http://localhost:8080/MyApp'。
2。应用配置
检查您的 Web 应用程序的 <session-config>
配置是否设置正确。默认配置应该允许您的代码在无需添加任何特定内容的情况下工作,所以如果您没有添加任何内容,请不要担心这一点。但是,您可能想要确保没有任何东西可以阻止会话被重用。
- 应启用会话 cookie (
<tracking-mode>COOKIE</tracking-mode>
) - 超时应足够长,以便在第二次请求之前不会过期 (
<session-timeout>60</session-timeout>
) - 应正确设置 cookie 路径以供您使用 (
<path>/</path>
)
以下是我常用的会话配置…
<session-config>
<session-timeout>60</session-timeout>
<tracking-mode>COOKIE</tracking-mode>
<cookie-config>
<path>/</path>
<http-only>true</http-only>
<secure>false</secure>
</cookie-config>
</session-config>
3。客户端会话 Cookie 跟踪
如果以上几点不能解决问题,您可以通过监控您的应用程序和客户端浏览器之间的请求和响应流量来真正开始深入研究会话跟踪。会话信息由名为“JSESSIONID”的 cookie(如果禁用 cookie 则为查询字符串参数)来回传递。它的值将是唯一会话的 ID,并且每个请求都必须相同,以确保您的 Web 应用程序跟踪相同的会话。下面重点介绍了一些需要寻找的东西……
确保“JSESSIONID”会话 cookie 已正确发送到客户端浏览器,并随每个后续请求一起发回。您可以使用 Chrome 或 Safari 的网络开发工具(在 'Network' 选项卡下)或使用单独的实用程序(例如 Wireshark)来完成此操作。
- 确保 'JSESSIONID' cookie 存在于第一个请求的响应中……这会让您知道您的网络应用程序至少正在创建会话和响应 cookie。
- 确保来自客户端浏览器的第二个请求将 'JSESSIONID' cookie 传回...这是您的网络应用知道要使用哪个现有会话的唯一方法。
- 确保 'JESSIONID' cookie 的路径为“/”(在浏览器中可能显示为 'N/A')或您的网络应用程序的路径(例如“/MyApp” )… 客户端浏览器只会将 cookie 发送到与每个域关联的域和路径。例如,如果您的登录页面是“http://example.com/MyApp/login', the 'JSESSIONID' cookie may have a path of '/MyApp' (by default), which will not be returned if the following request is made to 'http://example.com/”(没有“/MyApp”路径)。默认路径是您的网络应用程序的名称(“/MyApp”),可以使用上面指示的
<path>
配置项进行更改。
4. Bean 中的会话管理(附加信息)
在您的 initialiseSession()
方法中,FacesContext.getCurrentInstance().getExternalContext().getSession(true);
返回的会话对象没有被保存,这一行实际上什么也没做。在调用 initialiseSession()
之前,@SessionScoped
注释将已经创建了一个会话并将“JSESSIONID”cookie 添加到响应中。因此,调用 getSession(true)
的唯一原因是如果您想将会话保存到 bean 中的私有对象,就像这样...
@ManagedBean
@SessionScoped
public class LoginController extends AbstractController{
// Create a global, private member for storing the session data...
private HttpSession session;
@PostConstruct
public void initialiseSession() {
// Assign the session to the global member…
session = FacesContext.getCurrentInstance().getExternalContext().getSession(true);
}
…
同样,在您的示例中不需要调用 getSession(true)
,因为 SessionScoped
bean 已经创建了会话。仅当您打算更新或使用会话对象时才需要上述代码,例如添加属性或修改设置。
总结
仔细检查以上第 1 - 3 点。我的假设是“JSESSIONID”cookie 不会在后续请求中发回。如果您可以确认每个请求中都包含“JSESSIONID”cookie(具有相同的值),那么问题与会话无关,可能与您的 login()
方法中的代码有关。