| 加入收藏| 设为首页| 联系我们

首页 站长学习 站长之家 源码下载 建站素材 书籍教程 常用工具
 您现在的位置: 动力中国 >> 网络编程 >> JSP教程 >> 文章正文  
 [图文]Tomcat中的Session和Cookie大揭密
 

Tomcat中的Session和Cookie大揭密

http://www.domcn.org  文章来源:本站收藏  点击数:

  关键字:Tomcat中的Session和Cookie大揭密

一、JSP和Servlet中的Cookie

    由于HTTP协议是无状态协议(虽然Socket连接是有状态的,但每次用HTTP协议进行数据传输后就关闭的Socket连接,因此,HTTP协议并不会保存上一次的状态),因此,如果要保存某些HTTP请求过程中所产生的数据,就必须要有一种类似全局变量的机制保证数据在不同的HTTP请求之间共享。这就是下面要讲的Session和Cookie。
    Cookie是通过将数据保存在客户端的硬盘(永久Cookie)或内存(临时Cookie)中来实现数据共享的一种机制。在Windows下,保存在这些Cookie数据的目录一般是C:\Documents and Settings\Administrator\Cookies。每一个Cookie有一个超时时间,如果超过了这个时间,Cookie将自动失效。可按如下方法来设置Cookie的超时时间:

    Cookie cookie = new Cookie(key,value);
cookie.setMaxAge(3600);  // Cookie的超时间为3600秒,也就是1小时
    response.addCookie(cookie);
如果不使用setMaxAge方法,Cookie的超时时间为-1,在这种情况下,Cookie就是临时Cookie,也就是说这种Cookie实际上并不保存在客户端硬盘上,而是保存在客户端内存中的。读者可以在JSP中运行如下代码,看看是否会在上面提到的保存cookie的目录中生成cookie文件:

 Cookie cookie = new Cookie(key,value);
response.addCookie(cookie);
实际上使用setMaxAge将超时时间设为任意的负数都会被客户端浏览器认为是临时Cookie,如下面的代码将在客户端内存中保存一个临时Cookie:

Cookie cookie = new Cookie(key,value);
cookie.setMaxAge(-100);  // 将cookie设为临时Cookie
    response.addCookie(cookie);
如果第一次将Cookie写入客户端(不管是硬盘还是内存),在同一台机器上第二次访问 该网站的jsp页面时,会自动将客户端的cookie作为HTTP请求头的Cookie字段值传给服务端,如果有多个Cookie,中间用;隔开。如下面的HTTP请求头所示:   GET /test/First.jsp HTTP/1.1 HOST:localhost ... Cookie:key1=value1;key2=value2 ... ...

    我们可以在JSP中使用如下的Java代码来输出Cookie字段的值:      out.println(request.getHeader(Cookie));   如果在Servlet中输出,必须得使用如下语句得到out,才能向客户端浏览器输出数据:
       PrintWriter out = response.getWriter();

    虽然永久Cookie和临时Cookie在第二次向服务端发出HTTP请求时生成Cookie字段,但它们还是有一定的区别的。永久Cookie在任意新开启的IE窗口都可以生成Cookie。而临时Cookie由于只保存在当前IE窗口,因此,在新开启的IE窗口,是不能生成Cookie字段的,也就是说,新窗口和旧窗口是不能共享临时Cookie的。使用重定向机制弹出的新窗口也无法和旧窗口共享临时Cookie。但在同一个窗口可以。如在一个IE窗口输入http://localhost:8080/test/first.jsp,向内存写入一个临时Cookie后,在同一个IE窗口输入http://localhost:8080/test/second.jsp,浏览器在向服务端发送HTTP请求时,自动将当前浏览器的临时Cookie(也就是first.jsp所创建的Cookie)和永久Cookie作为HTTP请求头的Cookie字段值发送给服务端。但是如果新启一个IE窗口,由于新IE窗口没有这个临时Cookie,因此,second.jsp只发送了保存在硬盘上的永久Cookie。 二、Tomcat中的Servlet和Session

    由于Cookie数存在保存在客户端,这样对于一些敏感数据会带来一些风险。而且Cookie一般只能保存字符串等简单数据。并且大小限制在4KB。如果要保存比较复杂的数据,Cookie可能显得有些不合适。基于这些原因,我们自然会想到在服务端采用这种类似Cookie的机制来存储数据。这就是我们这节要讲的会话(Session)。而在一个客户端和服务端的会话中所有的页面可以共享为这个会话所建立的Session。

    那么什么是会话呢?有很多人认为会话就是在一台机器上客户端浏览器访问某个域名所指向的服务端程序,就建立了一个客户端到服务端的会话。然后关闭客户端浏览器,会话就结束。其实这并不准确。
    首先让我们先来看看Session的原理。Session和Cookie类似。所不同的是它是建立在服务端的对象。每一个Session对象一个会话。也许很多读者看到这会有一个疑问。Session是如何同客户端联系在一起的呢?很多人在使用Session时并没有感觉到这一点。其实这一切都是Web服务器,如Tomcat一手包办的。那么Web服务器又是如何识别通过HTTP协议进行连接的客户端的呢?这就要用到第一节中所讲的Cookie。在一般情况下,Session使用了临时Cookie来识别某一个Session是否属于某一个会话。在本文中以Tomcat为例来说明Session是如何工作的。

    让我们先假设某一个客户端第一次访问一个Servlet,在这个Servlet中使用了getSession来得到一个Session对象,也就是建立了一个会话,这个Servlet的代码如下:

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class First extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType(text/html);
HttpSession session = request.getSession();
session.setAttribute(key, mySessionValue);
PrintWriter out = response.getWriter();
out.println(The session has been generated!);
out.flush();
out.close();
}
}
对于服务端的First来说,getSession方法主要做了两件事:     1. 从客户端的HTTP请求头的Cookie字段中获得一个寻找一个JSESSIONID的key,这个key的值是一个唯一字符串,类似于D5A5C79F3C8E8653BC8B4F0860BFDBCD 。    
2. 如果Cookie中包含这个JSESSIONID,将key的值取出,在Tomcat的Session Map(用于保存Tomcat自启动以来的所有创建的Session)中查找,如果找到,将这个Session取出,如果未找到,创建一个HttpSession对象,并保存在Session Map中,以便下一次使用这个Key来获得这个Session。   在服务器向客户端发送响应信息时,如果是新创建的HttpSession对象,在响应HTTP 头中加了一个Set-Cookie字段,并将JSESSIONID和相应的值反回给客户端。如下面的HTTP响应头:   HTTP/1.1 200 OK ... Set-Cookie: JSESSIONID=D5A5C79F3C8E8653BC8B4F0860BFDBCD ...
    对于客户端浏览器来说,并不认识哪个Cookie是用于Session的,它只是将相应的临时Cookie和永久Cookie原封不动地放到请求HTTP头的Cookie字段中,发送给服务器。如果在IE中首次访问服务端的First,这时在当前IE窗口并没有临时Cookie,因此,在请求HTTP头中就没有Cookie字段,所以First在调用getSession方法时就未找到JSESSIONID,因此,就会新建一个HttpSession对象。并在Set-Cookie中将这个JSESSIONID返回。接下来我们使用另外一个Servlet:Second来获得在First中所设置的Session数据。Second的代码如下:
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class Second extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType(text/html);
HttpSession session = request.getSession();
PrintWriter out = response.getWriter();
out.println(session.getAttribute(key));
out.flush();
out.close();
}
}
     如果在同一个窗口来调用Second。这时客户端已经有了一个临时Cookie,就是JSESSIONID,因此,会将这个Cookie放到HTTP头的Cookie字段中发送给服务端。服务端在收到这个HTTP请求时就可以从Cookie中得到JSESSIONID的值,并从Session Map中找到这个Session对象,也就是getSession方法的返回值。因此,从技术层面上来说,所有拥有同一个Session ID的页面都应该属于同一个会话。

    如果我们在一个新的IE窗口调用Second,并不会得到mySessionValue。因为这时Second和First拥有了不同的Session ID,因此,它们并不属于同一个会话。讲到这,也许很多读者眼前一亮。既然拥有同一个Session ID,就可以共享Session对象,那么我们可不可以使用永久Cookie将这个Session ID保存在Cookie文件中,这样就算在新的IE窗口,也可以共享Session对象了。答案是肯定的。下面是新的First代码:
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class First extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType(text/html);
HttpSession session = request.getSession();
session.setMaxInactiveInterval(3600);
Cookie cookie = new Cookie(JSESSIONID, session.getId());
cookie.setMaxAge(3600);
response.addCookie(cookie);
session.setAttribute(key, mySessionValue);
PrintWriter out = response.getWriter();
out.println(The session has been generated!);
out.flush();
out.close();
}
}
    在上面的代码中使用了Cookie对象将JSESSIONID写入了Cookie文件,并使用setMaxAge方法将Cookie超时时间设为3600秒(1小时)。这样只要访问过First,从访问时间算起,在1小时之内,在本机的任何IE窗口调用Second都会得到mySessionValue字符串。 三、Tomcat中的JSP和Session
    从本质上讲,JSP在运行时已经被编译成相应的Servlet了,因此,在JSP和Servlet中Session的使用方法应该差不多。但还是有一些细小的差别。

    如果我们使用过JSP就会发现,在JSP中很多对象是不需要创建的,如out、session等。它们可以直接使用。如下面的JSP代码所示:

<!-- MyJSP.jsp -->

<%@ page language=java contentType=text/html; charset=GB18030
    pageEncoding=GB18030%>
<!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=GB18030>
        <title>Insert title here</title>
    </head>
    <body>
        <%
out.println(session.getId());
%>
    </body>
</html>
    在上面的JSP代码中直接使用了out和session。而并不象Servlet里一样用get方法来获得相应的对象实例。那么这是为什么呢?

    由于JSP在第一次运行时是被编译成Servlet的,我们自然就会想到有可能是在编译JSP时自动创建了session和out对象。下面我们就来验证这一点。首先需要查看一下JSP被编译成Servlet后的源代码。这非常简单,如果我们使用的是Tomcat,只需要在Tomcat的安装目录中的work中找相应的源程序即可。如一个名为MyJSP.jsp的文件首先被编译成MyJSP_jsp.java(这就是由JSP生成的Servlet源程序文件),然后再由java将MyJSP_jsp.java编译成MyJSP_jsp.class,最后Tomcat运行的就是MyJSP_jsp.class。如上面的JSP程序被编译成Servlet的部分源代码如下:

package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class MyJSP_jsp extends org.apache.jasper.runtime.HttpJspBase
{
... ...
... ...
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
response.setContentType(text/html; charset=GB18030);
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
ses

[1] [2] 下一页


Tomcat中的Session和Cookie大揭密
  • 上一篇文章:

  • 下一篇文章:
  •  热门文章
    普通文章 电子邮件改头换面 四公司畅谈未
    普通文章 PC病毒史上最声名狼藉的八大病
    普通文章 Rails系统中的AJAX开发技术简析
    普通文章 基于ASP.NET AJAX框架实现表单
    普通文章 开发ASP.NET AJAX客户端定制行
    普通文章 用JFreeChart对JSP报表进行增强
    普通文章 SQL Server 2005上的CLR和ADO.
    普通文章 SQL Server 2005的XML支持机制
    普通文章 Firefox中标签式浏览技巧大全
    普通文章 Tomcat中的Session和Cookie大揭
     
     推荐文章
    推荐文章 把Google地图嵌入网页 就是这么
    推荐文章 迅雷搜索候选资源出错的解决
    推荐文章 轻松去除迅雷里的各种广告和资
    推荐文章 突破限制 免费领养到QQ空间五级
    推荐文章 Rational统一过程RUP贴近中小软
    推荐文章 构建自己的轻量级XML DOM分析程
    推荐文章 WPS Office 2007技巧:妙用配置
    推荐文章 Excel 2007:求余数函数实用进阶
    推荐文章 浅谈ASP.NET的Postback
    推荐文章 软件开发中项目需求管理简述
     
     相关文章
    没有相关文章
    设为首页 | 加入收藏 | 广告合作 | 联系站长 | 版权申明 |
    动力中国为网友提供免费学习资料,可用资源,如果您认为我们的相关内容侵害到了您的权利请联系管理员
    Copyright © 2006-2008 domcn.org All Rights Reserved.