Session 实现原理

本贴最后更新于 2823 天前,其中的信息可能已经物是人非

Session 实现原理

标签: sessionserverurlheaderwebhtml

分类:

web 开发_(9)_

Session 实现原理

2008-08-26 17:11

关键字: jsp,session

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.fastfish/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:Session 对象在浏览器中的有效范围:
IE 中:
1〉.Session 对象只在建立 Session 对象的窗口中有效。
2〉.在建立 Session 对象的窗口中新开链接的窗口也有效。
Session 只会在内存中,他会随着 IE 窗口的关闭而死亡。
也就是说单用 seesion 是不会有产生自动登入的效果的。
2:Cookie 是在服务器给客户端 IE 一个命令后在客户端产生并存的,
它可以存放用户信息,存到客户端硬盘上,在 COOKIE 记录被删除
或者失效日期之前,就可以实现自动登入的现象。
3:Session 和 Cookie 是不同的,但是他们确实是相关的。
当打开 IE 登入后,会向服务器发出一个指令请求 SESSIONID 以
及页面内容,服务器会返回页面内容和一个没有被使用的
SESSIONID 让此 IE 使用,当时 IE 就对返回 SESSIONID 做存储;而当此 IE 再访问任何这个站点的 JSP 程序的时候,都会给服务器这个 SESSIONID,来确认客户端的身份。(在没有 Cookie 的情况下 session 死亡 SESSIONID 被取消就需要重新登入)
4:可以通过客户端禁用和不禁用 cookie 来验证自己的说法。

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    944 引用 • 943 回帖
  • 七牛云

    七牛云是国内领先的企业级公有云服务商,致力于打造以数据为核心的场景化 PaaS 服务。围绕富媒体场景,七牛先后推出了对象存储,融合 CDN 加速,数据通用处理,内容反垃圾服务,以及直播云服务等。

    27 引用 • 225 回帖 • 168 关注
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有计划重制上线。

    14 引用 • 257 回帖 • 1 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 2 关注
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    497 引用 • 1387 回帖 • 284 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖 • 1 关注
  • 博客

    记录并分享人生的经历。

    273 引用 • 2388 回帖
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖 • 1 关注
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 134 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    5 引用 • 107 回帖
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    132 引用 • 1114 回帖 • 125 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 351 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    286 引用 • 248 回帖 • 62 关注
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    107 引用 • 295 回帖 • 1 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 10 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 75 关注
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 2 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖 • 1 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 5 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 41 关注
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    179 引用 • 995 回帖 • 1 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 214 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    944 引用 • 1459 回帖 • 16 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 384 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    287 引用 • 4484 回帖 • 669 关注
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    20 引用 • 7 回帖