论坛首页 Java企业应用论坛

请教httpsession是如何实现的?

浏览 43161 次
该帖已经被评为精华帖
作者 正文
   发表时间:2005-01-23  
session功能实现原理是什么?session是如何唯一标识一个用户的?跟浏览器进程有关吗?
   发表时间:2005-01-23  
If the user's browser is cookie-enabled, the session ID is stored as a cookie. As an alternative, the session ID can be conveyed to the servlet by URL rewriting, in which the session ID is appended to the URL of the servlet or JavaServer Pages (JSP) file from which the user is making requests. For requests over HTTPS or Secure Sockets Layer (SSL), Another alternative is to use SSL information to identify the session
0 请登录后投票
   发表时间:2005-01-23  
URL rewriting话,如果我在一个页面左右两个框架分别登录两个站点,这样这个页面就有两个sessionid存储了,这样会出现问题吗?
0 请登录后投票
   发表时间:2005-01-23  
因为我出现了这样的问题,在一个框架的右页面登录另外一个站点后经常就取不到哪个session了
0 请登录后投票
   发表时间:2005-01-23  
然后如果新开一个窗口就是好的
0 请登录后投票
   发表时间:2005-01-23  
URL rewriting是怎么样工作的?
0 请登录后投票
   发表时间:2005-01-23  
HTTP协议(http://www.w3.org/Protocols/)是“一次性单向”协议。
服务端不能主动连接客户端,只能被动等待并答复客户端请求。客户端连接服务端,发出一个HTTP Request,服务端处理请求,并且返回一个HTTP Response给客户端,本次HTTP Request-Response Cycle结束。
我们看到,HTTP协议本身并不能支持服务端保存客户端的状态信息。于是,Web Server中引入了session的概念,用来保存客户端的状态信息。
这里用一个形象的比喻来解释session的工作方式。假设Web Server是一个商场的存包处,HTTP Request是一个顾客,第一次来到存包处,管理员把顾客的物品存放在某一个柜子里面(这个柜子就相当于Session),然后把一个号码牌交给这个顾客,作为取包凭证(这个号码牌就是Session ID)。顾客(HTTP Request)下一次来的时候,就要把号码牌(Session ID)交给存包处(Web Server)的管理员。管理员根据号码牌(Session ID)找到相应的柜子(Session),根据顾客(HTTP Request)的请求,Web Server可以取出、更换、添加柜子(Session)中的物品,Web Server也可以让顾客(HTTP Request)的号码牌和号码牌对应的柜子(Session)失效。顾客(HTTP Request)的忘性很大,管理员在顾客回去的时候(HTTP Response)都要重新提醒顾客记住自己的号码牌(Session ID)。这样,顾客(HTTP Request)下次来的时候,就又带着号码牌回来了。
我们可以看到,Session ID实际上是在客户端和服务端之间通过HTTP Request和HTTP Response传来传去的。

我们看到,号码牌(Session ID)必须包含在HTTP Request里面。关于HTTP Request的具体格式,请参见HTTP协议(http://www.w3.org/Protocols/)。这里只做一个简单的介绍。
在Java Web Server(即Servlet/JSP Server)中,Session ID用jsessionid表示(请参见Servlet规范)。
HTTP Request一般由3部分组成:
(1)Request Line
这一行由HTTP Method(如GET或POST)、URL、和HTTP版本号组成。
例如,GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
GET http://www.google.com/search?q=Tomcat HTTP/1.1
POST http://www.google.com/search HTTP/1.1
GET http://www.somsite.com/menu.do;jsessionid=1001 HTTP/1.1

(2)Request Headers
这部分定义了一些重要的头部信息,如,浏览器的种类,语言,类型。Request Headers中还可以包括Cookie的定义。例如:
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
Accept-Language: en-us
Cookie: jsessionid=1001

(3)Message Body
如果HTTP Method是GET,那么Message Body为空。
如果HTTP Method是POST,说明这个HTTP Request是submit一个HTML Form的结果,
那么Message Body为HTML Form里面定义的Input属性。例如,
user=guest
password=guest
jsessionid=1001
主意,如果把HTML Form元素的Method属性改为GET。那么,Message Body为空,所有的Input属性都会加在URL的后面。你在浏览器的URL地址栏中会看到这些属性,类似于
http://www.somesite/login.do?user=guest&password=guest&jsessionid=1001

从理论上来说,这3个部分(Request URL,Cookie Header, Message Body)都可以用来存放Session ID。由于Message Body方法必须需要一个包含Session ID的HTML Form,所以这种方法不通用。
一般用来实现Session的方法有两种:
(1)URL重写。
Web Server在返回Response的时候,检查页面中所有的URL,包括所有的连接,和HTML Form的Action属性,在这些URL后面加上“;jsessionid=XXX”。
下一次,用户访问这个页面中的URL。jsessionid就会传回到Web Server。
(2)Cookie。
如果客户端支持Cookie,Web Server在返回Response的时候,在Response的Header部分,加入一个“set-cookie: jsessionid=XXXX”header属性,把jsessionid放在Cookie里传到客户端。
客户端会把Cookie存放在本地文件里,下一次访问Web Server的时候,再把Cookie的信息放到HTTP Request的“Cookie”header属性里面,这样jsessionid就随着HTTP Request返回给Web Server。

我们来看Tomcat5的源代码如何支持jsessionid。
org.apache.coyote.tomcat5.CoyoteResponse类的toEncoded()方法支持URL重写。
String toEncoded(String url, String sessionId) {

        StringBuffer sb = new StringBuffer(path);
        if( sb.length() > 0 ) { // jsessionid can't be first.
            sb.append(";jsessionid=");
            sb.append(sessionId);
        }
        sb.append(anchor);
        sb.append(query);
        return (sb.toString());
}

我们来看org.apache.coyote.tomcat5.CoyoteRequest的两个方法configureSessionCookie()
doGetSession()用Cookie支持jsessionid.

    /**
     * Configures the given JSESSIONID cookie.
     *
     * @param cookie The JSESSIONID cookie to be configured
     */
    protected void configureSessionCookie(Cookie cookie) {
       …
    }

    HttpSession doGetSession(boolean create){
      …
        // Creating a new session cookie based on that session
        if ((session != null) && (getContext() != null)
               && getContext().getCookies()) {
            Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME,
                                       session.getId());
            configureSessionCookie(cookie);
            ((HttpServletResponse) response).addCookie(cookie);
        }
      …
    }

Session的典型应用是存放用户的Login信息,如用户名,密码,权限角色等信息,应用程序(如Email服务、网上银行等系统)根据这些信息进行身份验证和权限验证
1 请登录后投票
   发表时间:2005-01-23  
以上只是我的个人对Session的总结。不一定能够回答你的关于Frame的问题。

引用

URL rewriting话,如果我在一个页面左右两个框架分别登录两个站点,这样这个页面就有两个sessionid存储了,这样会出现问题吗?

因为我出现了这样的问题,在一个框架的右页面登录另外一个站点后经常就取不到哪个session了


你可以看一下,两个Frame里面的URL后面 带的URL?jessionid= 是否一样。
<Form Action="">  <a href="">
或者到你的系统的 internet template data目录下面,查找该站点的Cookie信息,查看里面的jssessionid。

也许同一个浏览器窗口内,两个Frame用的是同一个Session。你后来 右边Frame 登陆的信息,冲掉了之前 左边Frame 的登陆信息。

引用

然后如果新开一个窗口就是好的


如果是单Frame页面,新开一个浏览器窗口,Session会复制过去。两个浏览器会共享一个Session。

---

关于Cookie,好像还分为Primary Cookie,和Secondary Cookie。
我不太了解这两者的区别。

另外,Javaeye 还有一个帖子,关于 Single Sign On 单点登陆。
http://forum.iteye.com/viewtopic.php?t=6473

讨论了Cookie实现 SSO的方案。也许有一点相关性。
0 请登录后投票
   发表时间:2005-02-02  
多谢buaawhl指点,前几日因发这个帖子被禁止登录,^_^
0 请登录后投票
   发表时间:2005-12-28  
好文:)
解决了很多困惑,呵呵
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics