聶永的博客

          記錄工作/學(xué)習(xí)的點(diǎn)點(diǎn)滴滴。

          Servlet 3.0筆記之會(huì)話Cookie設(shè)置相關(guān)

          在Servlet 3.0中增加對(duì)Cookie(請(qǐng)注意,這里所說(shuō)的Cookie,僅指和Session互動(dòng)的Cookie,即人們常說(shuō)的會(huì)話Cookie)較為全面的操作API。最為突出特性:支持直接修改Session ID的名稱(默認(rèn)為“JSESSIONID”),支持對(duì)cookie設(shè)置HttpOnly屬性以增強(qiáng)安全,避免一定程度的跨站攻擊。
          相關(guān)較為深入信息,請(qǐng)?jiān)L問(wèn)進(jìn)階閱讀部分。
          以前的實(shí)現(xiàn)
          雖然新的API提供了簡(jiǎn)答便捷的API操作會(huì)話Cookie,但新的API之前,我們可以較為生硬的操作響應(yīng)頭部,完成設(shè)定工作。看看以前的代碼吧:
          /**
          * 自定義會(huì)話Cookie屬性
          * @author yongboy
          * @date 2011-1-19
          * @version 1.0
          */
          @WebFilter(dispatcherTypes = { DispatcherType.REQUEST }, urlPatterns = { "/*" })
          public class CustomCookieFilter implements Filter {
          private static final Log log = LogFactory.getLog(CustomCookieFilter.class);
          private static final String CUSTOM_SESSION_ID = "YONGBOYID";
          private static final String HTTP_ONLY = "HttpOnly";
          private static final String SET_COOKIE = "SET-COOKIE";

          public void destroy() {
          }

          public void doFilter(ServletRequest req, ServletResponse rep,
          FilterChain chain) throws IOException, ServletException {
          HttpServletRequest request = (HttpServletRequest) req;
          HttpServletResponse response = (HttpServletResponse) rep;

          if (response.containsHeader(SET_COOKIE)) {
          log.info("haha,we have one new user visit the site ...");

          String sessionId = request.getSession().getId();
          String cookieValue = CUSTOM_SESSION_ID + "=" + sessionId + ";Path="
          + request.getContextPath() + ";" + HTTP_ONLY;

          log.info(SET_COOKIE + ":" + cookieValue);

          response.setHeader(SET_COOKIE, cookieValue);
          }

          chain.doFilter(req, response);
          }

          public void init(FilterConfig fConfig) throws ServletException {
          }
          }

          利用攔截器實(shí)現(xiàn),判斷每次請(qǐng)求的響應(yīng)是否包含SET-COOKIE頭部,重寫(xiě)會(huì)話Cookie,添加需要的屬性。雖較為生硬,但靈活性強(qiáng)。

          新的規(guī)范API

          新的規(guī)范添加SessionCookieConfig接口,用于操作會(huì)話Cookie,需要掌握以下主要方法:
          1. setName(String name)
            修改Session ID的名稱,默認(rèn)為"JSESSIONID"
          2. setDomain(String domain)
            設(shè)置當(dāng)前Cookie所處于的域
          3. setPath(String path)
            設(shè)置當(dāng)前Cookie所處于的相對(duì)路徑
          4. setHttpOnly(boolean httpOnly)
            設(shè)置是否支持HttpOnly屬性
          5. setSecure(boolean secure)
            若使用HTTPS安全連接,則需要設(shè)置其屬性為true
          6. setMaxAge(int maxAge)
            設(shè)置存活時(shí)間,單位為秒
          如何使用呢,很方便,在ServletContextListener監(jiān)聽(tīng)器初始化方法中進(jìn)行設(shè)定即可;下面實(shí)例演示如何修改"JSESSIONID",以及添加支持HttpOnly支持:
          /** 全局設(shè)置Session-Cookie相交互部分屬性
          *
          * @author yongboy
          * @date 2011-1-19
          * @version 1.0
          */
          @WebListener
          public class SessionCookieInitialization implements ServletContextListener {
          private static final Log log = LogFactory
          .getLog(SessionCookieInitialization.class);

          public void contextInitialized(ServletContextEvent sce) {
          log.info("now init the Session Cookie");

          ServletContext servletContext = sce.getServletContext();

          SessionCookieConfig sessionCookie = servletContext
          .getSessionCookieConfig();
          sessionCookie.setName("YONGBOYID");
          sessionCookie.setPath(servletContext.getContextPath());
          sessionCookie.setHttpOnly(true);
          sessionCookie.setSecure(false);

          log.info("name : " + sessionCookie.getName() + "\n" + "domain:"
          + sessionCookie.getDomain() + "\npath:"
          + sessionCookie.getPath() + "\nage:"
          + sessionCookie.getMaxAge());

          log.info("isHttpOnly : " + sessionCookie.isHttpOnly());
          log.info("isSecure : " + sessionCookie.isSecure());
          }

          public void contextDestroyed(ServletContextEvent sce) {
          log.info("the context is destroyed !");
          }
          }
          需要通過(guò)ServletContext對(duì)象獲得SessionCookieConfig對(duì)象,才能夠進(jìn)一步自定義session cookie的名字等屬性。
          無(wú)論以前的硬編碼還是新的API實(shí)現(xiàn),目標(biāo)都是一致的,所產(chǎn)生頭部信息也是完全一致。毫無(wú)疑問(wèn),后者更為方便快捷,省缺了顯示的操作響應(yīng)元數(shù)據(jù)。
          對(duì)當(dāng)前站點(diǎn)的第一次請(qǐng)求,很容易從響應(yīng)頭信息中看到Set-Cookie的屬性值:

          image


          不同瀏覽器平臺(tái)上測(cè)試

          1. 在Safari、IE8、Opera 11 一切都很正常
          2. Firefox 3.6、Chrome 9.0,JSESSIONID會(huì)繼續(xù)存在:
            YONGBOYID=601A6C82D535343163B175A4FD5376EA; JSESSIONID=AA78738AB1EAD1F9C649F705EC64D92D; AJSTAT_ok_times=6; JSESSIONID=abcpxyJmIpBVz6WHVo_1s; BAYEUX_BROWSER=439-1vyje1gmqt8y8giva7pqsu1
          3. 在所有瀏覽器中,SESSION ID等于新設(shè)置的YONGBOYID值(若不相等,問(wèn)題就嚴(yán)重了!)
          4. 在客戶端JS無(wú)法獲得正確的SESSIONI ID了。
          Tomcat服務(wù)器內(nèi)置支持

          在Tomcat 6-7,可以不用如上顯示設(shè)置Cookie domain、name、HttpOnly支持,在conf/context.xml文件中配置即可:
          <Context useHttpOnly="true", sessionCookieName="YONGBOYID", sessionCookieDomain="/servlet3" … >
          ...
          </Context>
          既然JAVA應(yīng)用服務(wù)器本身支持會(huì)話Cookie設(shè)定,那就沒(méi)有必要在程序代碼中再次進(jìn)行編碼了。這是一個(gè)好的實(shí)踐:不要重復(fù)造輪子。
          這里給出一段測(cè)試Session重寫(xiě)的一段腳本:
          <div style="margin: 40px; paddding: 10px">
          <div><a href="sessionCookieTest">正常連接</a></div>
          <div><a href="<%=response.encodeURL("sessionCookieTest") %>">重定向連接</a></div>
          </div>
          會(huì)被重寫(xiě)的URL地址類似于:
          http://localhost/servlet3/sessionCookieTest;YONGBOYID=19B94935D50245270060E49C9E69F5B6
          嗯,在取消會(huì)話Cookie之后,可以直接看到修改后的SESSION ID名稱了,當(dāng)然這時(shí)候HttpOnly屬性也沒(méi)有多大意義了。
          有一點(diǎn)別忘記,設(shè)置HttpOnly之后,客戶端的JS將無(wú)法獲取的到會(huì)話ID了。

          進(jìn)階閱讀:

          1. 維基對(duì)HttpOnly的解釋
          2. 利用HTTP-only Cookie緩解XSS之痛
          3. Tomcat Context 屬性
          4. HttpOnly cookie與跨站點(diǎn)追蹤

          posted on 2011-01-19 21:58 nieyong 閱讀(7913) 評(píng)論(0)  編輯  收藏 所屬分類: Servlet3

          公告

          所有文章皆為原創(chuàng),若轉(zhuǎn)載請(qǐng)標(biāo)明出處,謝謝~

          新浪微博,歡迎關(guān)注:

          導(dǎo)航

          <2011年1月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          統(tǒng)計(jì)

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個(gè)人收藏

          最新隨筆

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 津市市| 龙陵县| 宁海县| 武鸣县| 云和县| 工布江达县| 光泽县| 南郑县| 朔州市| 邯郸县| 房山区| 黑河市| 南雄市| 咸阳市| 合作市| 桂阳县| 高雄县| 长寿区| 皮山县| 临潭县| 乌鲁木齐市| 武城县| 泾川县| 邵阳市| 廉江市| 宝清县| 安西县| 梁平县| 新巴尔虎左旗| 屏山县| 肥东县| 大化| 新乡县| 林西县| 永兴县| 旬邑县| 龙井市| 和平县| 西宁市| 阿勒泰市| 宁波市|