From Gossip@caterpillar

JSP/Servlet: session (2)

 

 


session(HttpSession)物件會在使用者第一次存取Web伺服器時產生,伺服器會產生一個獨特的 session id來表示這個客戶端,瀏覽器在之後的每次請求中都包括這個session id(可能是使用Cookie或是URL rewriting,這個細節不用您來擔心),伺服器根據這個session id來對應該客戶端的session物件,您可以使用getId()方法來取得session id,例如:
<%
    out.println("Session ID:" + session.getId());
%>

顯示的session id型式如下:
Session ID:2F892EDF2669858811B8D121119AE90B

session id預設是使用Cookie來儲存於客戶端,並在每一次瀏覽器發送請求時夾帶這個訊息給伺服器,伺服器根據session id來對應出HttpSession物件,假如Cookie沒有開啟,則瀏覽器將無法儲存session id,也就無法將session id的訊息傳送給伺服器,也就無法進行進程追蹤,即使資料物件確實儲存於HttpSession中,您也無法取出,下面這個程式在瀏覽器Cookie功能 關閉的情況下,只會一直顯示session not found, reset!訊息:

  • sessionDemo.jsp
<%@page contentType="text/html;charset=Big5"%> 
<html>
<head><title>session demo</title></head>
<body>
<H1>
<%
if(session.getAttribute("info") == null) {
session.setAttribute("info",
"session information");
out.println("session not found, reset!");
}
else {
out.println("session found: " +
session.getAttribute("info"));
}
%>
</H1>
</body>
</html>

如果Cookie功能關閉,則session id無法儲存,也就無法在下一次請求時一併送至伺服器,為了讓進程追蹤得以進行,您必須使用URL rewriting來傳送session id,所幸的是有一個簡單的方法可以幫您進行這個動作,使用response的encodeURL()可以自動將session id編進URL中,例如:
  • sessionDemo.jsp
<%@page contentType="text/html;charset=Big5"%> 
<html>
<head><title>session demo</title></head>
<body>
<H1>
<%
if(session.getAttribute("info") == null) {
session.setAttribute("info",
"session information");
out.println("session not found, reset!");
}
else {
out.println("session found: " +
session.getAttribute("info"));
}

out.println("<br><a href='" +
response.encodeURL("sessionDemo.jsp") +
"'>" + "進程追蹤" + "</a>");
%>
</H1>
</body>
</html>

如果您的瀏覽器Cookie功能關閉,您必須使用response的encodeURL()自動將session id編進URL中,如果Cookie功能可以運作,則encodeURL()會原封不動的傳回指定的URL,否則會在指定的URL後加上sessiond id,例如上面的JSP網頁在Cookie功能關閉的情況下,會傳回以下的內容:
<html>
<head><title>session demo</title></head>
<body>
<H1>
    session not found, reset!
<br><a href='sessiondemo.jsp;jsessionid=
      7A2A0BFA32D0022D8BB80A5E690A9D10'>進程追蹤</a>
 
</H1>
</body>
</html>

簡單的說,按下經過URL rewriting的連結,瀏覽器就可以將session id傳送至伺服器,然而您的網址列上就會出現session id的訊息:
http://localhost:8080/myjsp/sessionDemo.jsp;jsessionid=7A2A0BFA32D0022D8BB80A5E690A9D10

這是一個有危險性的訊息,任何人只要在session的存活期限獲得這個訊息,就可以進行進程追蹤,所以基本上還是建議使用者開啟Cookie功能,以免 session id曝露在網址列上。

在上一個主題中的登入網頁如果在Cookie功能關閉的情況下也將無法運作,您必須這樣改寫login.jsp:

  • login.jsp
<%@page contentType="text.html;charset=Big5"%> 
<%
String user = request.getParameter("user");
String password =
request.getParameter("password");
String memberURL =
"http://localhost:8080/myjsp/member.jsp";
String loginFormURL =
"http://localhost:8080/myjsp/form.html";

if(user == null || password == null) {
response.setHeader("Refresh", "0; " + loginFormURL);
}
else if(user.equals("justin") && password.equals("1234")) {
session.setAttribute("user", user);
memberURL = response.encodeURL(memberURL);
response.setHeader("Refresh", "3; " + memberURL);
out.println(user + "歡迎登入!3秒後進入會員頁面!");
}
else {
response.setHeader("Refresh", "3; " + loginFormURL);
out.println(
"使用者或密碼錯誤,請重新登入(3秒後回到登入表單)");
}
%>

或者是您可以直接使用response的sendRedirect()方法,由於sendRedirect()要求完整的位址訊息,也就是包括http: //開始的位址訊息,您可以使用response的encodeRedirectURL()傳回這個位址,同樣的,如果 Cookie有開啟,則只是原封不動傳回原來指定的URL,您也可以改寫login.jsp程式如下:
  • login.jsp
<%@page contentType="text.html;charset=Big5"%> 
<%
String user = request.getParameter("user");
String password = request.getParameter("password");
String memberURL =
"http://localhost:8080/myjsp/member.jsp";
String loginFormURL =

"http://localhost:8080/myjsp/form.html";

if(user == null || password == null) {
response.setHeader("Refresh", "0; " + loginFormURL);
}
else if(user.equals("justin") && password.equals("1234")) {
session.setAttribute("user", user);
memberURL = response.encodeRedirectURL(memberURL);
response.sendRedirect(memberURL);
}
else {
response.setHeader("Refresh", "3; " + loginFormURL);
out.println(
"使用者或密碼錯誤,請重新登入(3秒後回到登入表單)");
}
%>

session具有其存活期限,關閉瀏覽器、伺服器關閉可能讓session失效,當客戶端停止活動一段時間(Tomcat預設是30分鐘), session會自動失效,您可以使用getMaxInactiveInterval()取得session的等待期限,取得的值以秒為單位,或是以 setMaxInactiveInterval()設定等待期限,設定的值也是以秒為單位:
<%
    out.println("default session life: " +
          session.getMaxInactiveInterval());
    session.setMaxInactiveInterval(600);
    out.println("now session life: " +
          session.getMaxInactiveInterval());
%>
 

您可以在web.xml中設定預設的session等待期限,使用<session-config>與<session- timeout>來進行設定,注意設定的單位為分鐘數,例如下面的設定將session等待期限預設為10分鐘:

  • web.xml
 ...
    <session-config>
        <session-timeout>
            10 <!--分鐘-->
        </session-timeout>
    </session-config>
...