您的位置:首页 > 运维架构 > Tomcat

session相关知识全接触03

2009-03-04 19:49 120 查看
七、跨应用程序的session共享3 s( x' e3 K' [$ f0 S; |* w

3 M7 [, S! x0 z; `: Y9 A' E: L) U- Z常常有这样的情况,一个大项目被分割成若干小项目开发,为了能够互不干扰,要求每个小项目作为一个单独的web应用程序开发,可是到了最后突然发现某几个小项目之间需要共享一些信息,或者想使用session来实现SSO(single sign on),在session中保存login的用户信息,最自然的要求是应用程序间能够访问彼此的session。
) k2 C: g; r) I+ U1 l, /) Q) i3 h! @( p0 X
然而按照Servlet 规范,session的作用范围应该仅仅限于当前应用程序下,不同的应用程序之间是不能够互相访问对方的session的。各个应用服务器从实际效果上都遵守了这一规范,但是实现的细节却可能各有不同,因此解决跨应用程序session共享的方法也各不相同。8 z$ y7 Z  v9 |# L- v1 b4 U: R2 U* d

, x7 Z& g2 ^  t6 U# m2 A  P' S8 d首先来看一下Tomcat是如何实现web应用程序之间session的隔离的,从 Tomcat设置的cookie路径来看,它对不同的应用程序设置的cookie路径是不同的,这样不同的应用程序所用的session id是不同的,因此即使在同一个浏览器窗口里访问不同的应用程序,发送给服务器的session id也可以是不同的。
1 ^2 K* S# B% v, t8 Z/ s4 X% a7 O- i% X" A# {. j& P. _+ T! `

! r' U8 v/ /' @ % v  _" _6 u, d. a/ B' c

. n3 y6 _6 T0 s+ ?根据这个特性,我们可以推测Tomcat中session的内存结构大致如下。
; _$ /' B8 /  U) H* |
! Z# n( r/ U0 Y$ b+ d7 /. C- u# i2 q/ Q

; @* _! U6 t) g* J) R3 q  j, Q9 N$ K. S
笔者以前用过的iPlanet也采用的是同样的方式,估计SunONE与iPlanet之间不会有太大的差别。对于这种方式的服务器,解决的思路很简单,实际实行起来也不难。要么让所有的应用程序共享一个session id,要么让应用程序能够获得其他应用程序的session id。5 u* |& J' e* a5 w9 V. e( ^

9 @) t" }2 Z1 T! [7 L0 t1 miPlanet中有一种很简单的方法来实现共享一个session id,那就是把各个应用程序的cookie路径都设为/(实际上应该是/NASApp,对于应用程序来讲它的作用相当于根)。5 y% p9 h, P- o2 w  p6 Y
<session-info>
. z3 U+ K# _* O) E7 P& w; x<path>/NASApp</path>
0 f! x- g. B8 R  c  a' P</session-info>
1 V, ]4 i. w  ]: u8 s
0 e" O8 l9 D1 [/ g) @) l* K+ ?需要注意的是,操作共享的session应该遵循一些编程约定,比如在session attribute名字的前面加上应用程序的前缀,使得 setAttribute("name", "neo")变成setAttribute("app1.name", "neo"),以防止命名空间冲突,导致互相覆盖。
2 E) D6 i- @5 C. ~* }" r! k7 L2 i- ?

( ^( G3 J) k3 i9 Q* @在Tomcat中则没有这么方便的选择。在Tomcat版本3上,我们还可以有一些手段来共享session。对于版本4以上的Tomcat,目前笔者尚未发现简单的办法。只能借助于第三方的力量,比如使用文件、数据库、JMS或者客户端cookie,URL参数或者隐藏字段等手段。
% }  g: h  I6 C. `* Q
2 k! O8 M+ U1 ]+ a# z) `. U% C我们再看一下Weblogic Server是如何处理session的。
, }+ u  v( /8 h2 e3 S
% G2 F! n1 g4 Q. }2 h- Y: a0 g- q0 /9 ~

9 Y6 O$ ?  t% L3 ?( L% r
, H5 X  F8 R0 n& Q( e从截屏画面上可以看到Weblogic Server对所有的应用程序设置的cookie的路径都是/,这是不是意味着在Weblogic Server中默认的就可以共享session了呢?然而一个小实验即可证明即使不同的应用程序使用的是同一个session,各个应用程序仍然只能访问自己所设置的那些属性。这说明Weblogic Server中的session的内存结构可能如下  i) v( u% B9 t' q. ?# H9 ^9 `
* N+ D( Q; x0 Z0 h3 t) s
5 f. _: U) d/ {/ s

6 R+ y" _& y$ {# s/ F" C) s! L  ]( r) K
对于这样一种结构,在 session机制本身上来解决session共享的问题应该是不可能的了。除了借助于第三方的力量,比如使用文件、数据库、JMS或者客户端 cookie,URL参数或者隐藏字段等手段,还有一种较为方便的做法,就是把一个应用程序的session放到ServletContext中,这样另外一个应用程序就可以从ServletContext中取得前一个应用程序的引用。示例代码如下,
6 M# H: v0 j3 N, k2 [/ }( i
* t- H. Y5 N3 p2 S应用程序A
) ~- W5 y2 s% n. c% x  y! mcontext.setAttribute("appA", session);' V- p$ n! ]3 y
& q! X/ ^1 C  `. r+ a3 X' ?
应用程序B
3 J3 K4 J0 ~; E; {contextA = context.getContext("/appA");# ?6 u0 J. L9 ]: V' ?" y
HttpSession sessionA = (HttpSession)contextA.getAttribute("appA");/ X- d4 s; j) F' p) u
; S2 R7 Z2 B7 n- Z6 a/ u- /+ m
值得注意的是这种用法不可移植,因为根据ServletContext的JavaDoc,应用服务器可以处于安全的原因对于context.getContext("/appA");返回空值,以上做法在Weblogic Server 8.1中通过。7 y: M: L+ t1 J* N

6 P8 `( u, s$ }  L( m, E4 S那么Weblogic Server为什么要把所有的应用程序的cookie路径都设为/呢?原来是为了SSO,凡是共享这个session的应用程序都可以共享认证的信息。一个简单的实验就可以证明这一点,修改首先登录的那个应用程序的描述符weblogic.xml,把cookie路径修改为/appA 访问另外一个应用程序会重新要求登录,即使是反过来,先访问cookie路径为/的应用程序,再访问修改过路径的这个,虽然不再提示登录,但是登录的用户信息也会丢失。注意做这个实验时认证方式应该使用FORM,因为浏览器和web服务器对basic认证方式有其他的处理方式,第二次请求的认证不是通过 session来实现的。具体请参看[7] secion 14.8 Authorization,你可以修改所附的示例程序来做这些试验。6 g& C9 L9 j: a7 y

! g7 N3 Z; _4 H7 m1 R& E八、总结
" S! f8 X( B' o6 B. dsession机制本身并不复杂,然而其实现和配置上的灵活性却使得具体情况复杂多变。这也要求我们不能把仅仅某一次的经验或者某一个浏览器,服务器的经验当作普遍适用的经验,而是始终需要具体情况具体分析。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息