JSESSIONIDセッションCookieがWebブラウザによって削除されると、サーバー側のセッションオブジェクトが失われることがわかりました。正しいIDなしでもう一度アクセスする方法はありません。
http://simple.souther.us/not-so-simple.htmlによって
主な考え方は、ユーザーのセッションをマップに登録してサーブレットのコンテキストに入れることです。セッションが作成されるたびに、キーのJSESSIONID値を使用してマップに追加されます。 JSESSIONIDクッキーが破棄された後でセッションを見つけるために、JSESSIONID値を記憶する永続クッキーも作成されます。
Webブラウザを閉じると、JSESSIONIDが破棄されます。しかし、すべてのHttpSessionオブジェクトのアドレスはサーバー側のマップに保持されており、永続的なCookieに保存された値で適切なセッションにアクセスできます。
まず、web.xmlデプロイメント記述子に2つのリスナーを追加します。
<listener>
<listener-class>
fr.hbonjour.strutsapp.listeners.CustomServletContextListener
</listener-class>
</listener>
<listener>
<listener-class>
fr.hbonjour.strutsapp.listeners.CustomHttpSessionListener
</listener-class>
</listener>
CustomServletContextListenerは、コンテキスト初期化時マップを作成します。このマップは、このアプリケーションでユーザーが作成したすべてのセッションを登録します。それが作成されたときに
/**
* Instanciates a HashMap for holding references to session objects, and
* binds it to context scope.
* Also instanciates the mock database (UserDB) and binds it to
* context scope.
* @author Ben Souther; [email protected]
* @since Sun May 8 18:57:10 EDT 2005
*/
public class CustomServletContextListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent event){
ServletContext context = event.getServletContext();
//
// instanciate a map to store references to all the active
// sessions and bind it to context scope.
//
HashMap activeUsers = new HashMap();
context.setAttribute("activeUsers", activeUsers);
}
/**
* Needed for the ServletContextListener interface.
*/
public void contextDestroyed(ServletContextEvent event){
// To overcome the problem with losing the session references
// during server restarts, put code here to serialize the
// activeUsers HashMap. Then put code in the contextInitialized
// method that reads and reloads it if it exists...
}
}
CustomHttpSessionListenerはactiveUsersマップにセッションを配置します。
/**
* Listens for session events and adds or removes references to
* to the context scoped HashMap accordingly.
* @author Ben Souther; [email protected]
* @since Sun May 8 18:57:10 EDT 2005
*/
public class CustomHttpSessionListener implements HttpSessionListener{
public void init(ServletConfig config){
}
/**
* Adds sessions to the context scoped HashMap when they begin.
*/
public void sessionCreated(HttpSessionEvent event){
HttpSession session = event.getSession();
ServletContext context = session.getServletContext();
HashMap<String, HttpSession> activeUsers = (HashMap<String, HttpSession>) context.getAttribute("activeUsers");
activeUsers.put(session.getId(), session);
context.setAttribute("activeUsers", activeUsers);
}
/**
* Removes sessions from the context scoped HashMap when they expire
* or are invalidated.
*/
public void sessionDestroyed(HttpSessionEvent event){
HttpSession session = event.getSession();
ServletContext context = session.getServletContext();
HashMap<String, HttpSession> activeUsers = (HashMap<String, HttpSession>)context.getAttribute("activeUsers");
activeUsers.remove(session.getId());
}
}
名/パスワードによるユーザーの真偽をテストするための基本的なフォームを使用します。このlogin.jspフォームは、テスト専用です。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title><bean:message key="formulaire1Title" /></title>
</head>
<body>
<form action="login.go" method="get">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="submit" />
</form>
</body>
</html>
ここに行きます。このJavaサーブレットは、ユーザーがセッション中でない場合はログインページに、ユーザーがいる場合は別のページに転送します。永続セッションをテストするためのものです。
public class Servlet2 extends AbstractServlet {
@Override
protected void doGet(HttpServletRequest pRequest,
HttpServletResponse pResponse) throws IOException, ServletException {
String username = (String) pRequest.getParameter("username");
String password = (String) pRequest.getParameter("password");
// Session Object
HttpSession l_session = null;
String l_sessionCookieId = getCookieValue(pRequest, "JSESSIONID");
String l_persistentCookieId = getCookieValue(pRequest, "MY_SESSION_COOKIE");
// If a session cookie has been created
if (l_sessionCookieId != null)
{
// If there isn't already a persistent session cookie
if (l_persistentCookieId == null)
{
addCookie(pResponse, "MY_SESSION_COOKIE", l_sessionCookieId, 1800);
}
}
// If a persistent session cookie has been created
if (l_persistentCookieId != null)
{
HashMap<String, HttpSession> l_activeUsers = (HashMap<String, HttpSession>) pRequest.getServletContext().getAttribute("activeUsers");
// Get the existing session
l_session = l_activeUsers.get(l_persistentCookieId);
}
// Otherwise a session has not been created
if (l_session == null)
{
// Create a new session
l_session = pRequest.getSession();
}
//If the user info is in session, move forward to another page
String forward = "/pages/displayUserInfo.jsp";
//Get the user
User user = (User) l_session.getAttribute("user");
//If there's no user
if (user == null)
{
// Put the user in session
if (username != null && password != null)
{
l_session.setAttribute("user", new User(username, password));
}
// Ask again for proper login
else
{
forward = "/pages/login.jsp";
}
}
//Forward
this.getServletContext().getRequestDispatcher(forward).forward(pRequest, pResponse);
}
MY_SESSION_COOKIEクッキーがJSESSIONIDクッキーの値を保存します。 JSESSIONID Cookieが破棄されると、MY_SESSION_COOKIEはまだセッションIDと共にそこにあります。
JSESSIONIDはWebブラウザセッションではなくなりましたが、永続的でシンプルなCookieと、アプリケーションコンテキストに配置されたすべてのアクティブセッションのマップを使用することを選択しました。永続的なCookieを使用すると、マップ内で適切なセッションを見つけることができます。
は、クッキーを追加/取得/削除するBalusCによって作られたこれらの便利なメソッドを忘れないでください:
/**
*
* @author BalusC
*/
public static String getCookieValue(HttpServletRequest request, String name) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName())) {
return cookie.getValue();
}
}
}
return null;
}
/**
*
* @author BalusC
*/
public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
Cookie cookie = new Cookie(name, value);
cookie.setPath("/");
cookie.setMaxAge(maxAge);
response.addCookie(cookie);
}
/**
*
* @author BalusC
*/
public static void removeCookie(HttpServletResponse response, String name) {
addCookie(response, name, null, 0);
}
}
最後の解決策は、Windows上で、ウェブブラウザのためのクロムと、ローカルホスト上のGlassFishで試験しました。これは単一のCookieにのみ依存し、データベースは必要ありません。しかし実際には、私はそのようなメカニズムの限界が何であるか分かりません。私はこの解決に来る夜を過ごしただけで、それが良いか悪いか分からずに過ごしました。私の答えに誤りがあるかどう
私はまだ学んでいる
THANKS、教えてください。ありがとう、@ +
[何ヶ月間ユーザーを自分のサイトにログインさせておくのですか?](http://stackoverflow.com/questions/2185951/java-how-do-i-keep-a-user-logged-into -my-site-for-months) – BalusC
関連:http://stackoverflow.com/questions/3106452/how-do-servlets-work-instantiation-session-variables-and-multithreading/3106909#3106909 – BalusC
このOWASPを読んでください[チートシート](https://www.owasp.org/index.php/Session_Management_Cheat_Sheet)。それは非常にいいリファレンスです。 – Hong