session-config
我們可以在web.xml對app的session進行設定:
<!-- 1、在session-config以及其裡面的cookie-config參數是可選的,但是他們必須按順序出現。 --><!-- 2、這些值都有預設值,我們可以不做處理,但是基於安全考慮,建議設定。 --><session-config><!-- session-timeout 單位分鐘,如果<=0,則表示無限期,tomcat的預設值是30分鐘,表示如果30分鐘內沒有收到新的request,認為session無效 --><session-timeout>30</session-timeout> <cookie-config><name>JSESSIONID</name> <!-- 名字,預設是JSESSIONID --><!-- domain和path對應Cookie中的Domain和Path屬性,這兩個數值一般採用預設,不要去設定,path預設是應用的context名字 --><domain>flowingflying.com</domain><path>/aaa</path> <!-- comment是Cookie頭中的Comment屬性,用於向使用者解析cookie的用途,並引導使用者到網站的隱私條例 --><comment>![CDATA[Keeps you logged in.See our private policy for more informcation.]]</comment><http-only>true</http-only> <!-- Cookie頭中的Http-Only屬性,防止跨站指令碼攻擊,利用javascript或第三方外掛程式讀取cookie --><secure>false</secure> <!-- Cookie頭中的Secure屬性,如果為true,只在https中使用cookie --><!-- Cookie頭中的Max-Age屬性,單位為秒,一般不設定,當瀏覽器關閉時cookie結束,如果設定-1,效果也一樣。可以設定為某個值,但這有可能使用者在瀏覽器用了半道,session就結束了。因此一般不設定。(注)很多瀏覽器選擇在關閉時仍記憶cookie,特別是案頭瀏覽器 --><max-age>1800</max-age> </cookie-config><!-- track-mode是在Servlet 3.0加入,表示container需要使用什麼技術跟蹤session id。--><!-- 1、URL:container將session ID嵌入到URL中,這種方式不安全 --><!-- 2、COOKIE:使用COOKIE,這種方式安全 --><!-- 3、SSL:使用SSL Session ID作為HTTP的session ID,這種最為安全,但是要求所以的請求都是HTTPS的。--><!-- 可以使用其中一種或者多種,如果不提供URL,則不會在URL中嵌入Session ID,--><!-- 如果同時採用URL,COOKIE,則優先採用COOKIE,同時也支援URL方式 --><!-- 如果採用了SSL,就不能採用URL或者COOKIE。 --><tracking-mode>COOKIE</tracking-mode><tracking-mode>URL</tracking-mode><tracking-mode>SSL</tracking-mode></session-config>
在代碼中,可以在ServletContextListener的contextInitialized()和ServletContainerInitializer的onStartup()中設定tracking mode和cookie-config。對ServletContext使用setSessionTrackingModes()進行設定;通過getSessionCookieConfig()擷取javax.servlet. SessionCookieConfig,然後進行設定。
下面是一個配置的例子:
<session-config><session-timeout>30</session-timeout> <cookie-config><path>/chapter05</path><http-only>true</http-only></cookie-config><tracking-mode>COOKIE</tracking-mode></session-config>
我們注意到有些瀏覽器關閉,然後重新開啟,發送的請求仍然會攜帶session ID在cookie中,例如firefox,很多案頭的瀏覽器均會如此,也即:瀏覽器關閉,cookie仍舊保持,在重啟後有效。這是由瀏覽器來決定如何處理的。 一個小例子
這是一個在購物車cart上加入貨品的例子,不使用資料庫,利用session進行存放。
//products是用來存放貨品id和貨品名稱的列表private final Map<Integer, String> products = new Hashtable<>();/* 請求中帶有product Id,表明使用者將該id對應的貨品放入到自己的cart中*/private void addToCart(HttpServletRequest request, HttpServletResponse response) throws IOException{int productId;try{productId = Integer.parseInt(request.getParameter("productId"));}catch(Exception e){response.sendRedirect("shop");return;}//getSession()等同於getSession(true),擷取session,如無,則建立新的,因此不會返回null。如果是getSession(false),則擷取session,如無,也不建立,返回null。HttpSession session = request.getSession();//在session中,使用者的cart的索引值對是("cart",HashMap對象),如無,包括request請求中沒有session ID以及雖有session ID但是並不在web container中存在的(可能web server重啟,可能到期什麼的),則建立之。Session中索引值對可以存放複雜的資料結構的對象,不只是簡單的String。刪除索引值對有session.removeAttribute( )方法。if(session.getAttribute("cart") == null)session.setAttribute("cart", new HashMap<Integer,Integer>());//在當中找到相應的貨品id,如果建立之,數量+1。@SuppressWarnings("unchecked")HashMap<Integer,Integer> cart = (HashMap<Integer,Integer>)session.getAttribute("cart");if(!cart.containsKey(productId)){cart.put(productId, 0);}cart.put(productId,cart.get(productId) + 1);//在使用者session的購物車中增加貨品後,調用購物車顯示業務,顯示給使用者看response.sendRedirect("shop?action=viewCart");}private void viewCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{request.setAttribute("products", products);request.getRequestDispatcher("/WEB-INF/jsp/view/viewCart.jsp").forward(request, response);}
上面是個java中使用session的例子,顯示購物車,通常採用jsp的方式,如上例將之forward到/WEB-INF/jsp/view/viewCart.jsp中進行處理。利用session.getAttribute()擷取session中的資訊。
<%@ page import="java.util.Map" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>View Cart</title></head><body><h2>View Cart</h2><%@SuppressWarnings("unchecked")Map<Integer,String> products = (Map<Integer,String>)request.getAttribute("products"); //使用session.getAttribute()擷取session中儲存的資訊@SuppressWarnings("unchecked")Map<Integer,Integer> cart = (Map<Integer,Integer>)session.getAttribute("cart");if(cart == null || cart.size() == 0){out.println("Your cart is empty.");}else{for(int id : cart.keySet()){out.println(products.get(id) + " (quantity:" + cart.get(id)+ ")<br/>");}}%></body></html>
其它常用方法
除了在小例子使用的方法,HttpSession還有以下常用的方法: getId():擷取session ID getCreationTime():建立時間 getLastAccessedTime(): 使用者最近一次request中帶有該session ID的時間 isNew():是否是建立的session ID getMaxInactiveInterval():是多長時間內無該session id的請求到達,則session無效。這個時間就是配置中的<session-timeout>的時間。相應的setMaxInactiveInterval可以用來針對該特定的session進行設定。例如管理員的許可權比一般使用者高,可以針對管理員的session,設定更短的時間。 invalidate():這個通常在使用者logout時調用,相當於刪除這個session。 Login和Logout
下面是使用者login成功後的處理:
//設定session的某個屬性,例如使用者名稱session.setAttribute("username", username); //修改session ID,避免使用者一直使用某個session id,這是避免fixation攻擊的一種方式,在Java EE 7版本後支援。request.changeSessionId();//登入後重新導向到某個頁面response.sendRedirect("/tickets");
其相應給出:
而在其它的servlet中:
//如果沒有註冊,返回登記介面if(request.getSession().getAttribute("username") == null){response.sendRedirect("/login");return;}
當使用者按logout,例如連結為/login?logout,那麼在login的servlet中doGet加上:
if(request.getParameter("logout") != null){session.invalidate();response.sendRedirect("login");return;}
相關連結: 我的Professional Java for Web Applications相關文章