Webx框架:会话管理

时间:2022-05-10 13:47:37

在Servlet中,Session和Cookie是分开的。Session一般保存在内存中,当然也可以保存在数据库等其他地方。如果保存在内存中,对于服务集群来说就需要解决Session共享的问题。如果保存在数据库,就存在单点故障、性能差等问题。

webx提供了会话框架,将session这样复杂的问题统一进行解决。在webx框架中,主张将cookie合并到session中,再通过规则,路由到cookie或者session中。cookie保存在客户端,session保存在服务端,它们的区别这里就不赘述了。

webx中有一个SessionStore的概念。它相当于Session的保存容器。容器可以配置不同的编码、加密方式等。与servlet配置类似,session的配置有storesstore-mappings。下面是一个简单的例子(仅用于调试):

<session>  <stores>    <session-stores:simple-memory-store id="simple" />  </stores>  <store-mappings>    <match name="*" store="simple" />  </store-mappings></session>

SessionID。在Servlet中,默认是通过名为JSESSIONID的Cookie保存SessionID。在webx中可以换用不同的Cookie名称,而且SessionID的生成方法也可以改变。下面是改变SessionID字段的例子。

<session>  <id cookieEnabled="true" urlEncodeEnabled="false">    <cookie name="JSESSIONID" domain="" maxAge="0" path="/" httpOnly="true" secure="false" />    <url-encode name="JSESSIONID" />    <session-idgens:uuid-generator />  </id></session>

Cookie属性有下面几个,都可以通过属性进行设置。namedomainmaxAgepathhttpOnlysecure

与其他框架不同的是,如果Http请求中的SessionID不认识,之前没有出现过,那么会将HTTP请求中的SessionID作为该客户端的SessionID,而不是创建一个新的。这样设计的好处是,有可能SessionID与其他应用共享,其他应用生成的SessionID是不能覆盖的。

会话RequestContext的属性有以下几个。

属性 作用
maxInactiveInterval Session的失效时间
keepInTouch 默认为false。如果为true,表示和servlet中的session模式一样,每次读取session的时候更新session,如果为false,只有在session内容发生改变时才更新session时间。
forceExpirationPeriod 无视失效时间,即使这个session一直被访问,超过这个事件,session还是会失效
modelKey 用于保存session状态的对象名称,一般不需要修改。默认为SESSION_MODEL
会话储存

SessionStore。下面是SessionStore的一个例子。

<stores>  <session-stores:store id="store1" />  <session-stores:store id="store2" />  <session-stores:store id="store3" /></stores><store-mappings>  <match name="*" store="store1" />  <match name="loginName" store="store2" />  <matchRegex pattern="key.*" store="store3" /></store-mappings>

match标签采用了正则匹配,如果有多个规则符合正则表达式,那么有下面的优先级:

  • 精确匹配最优先
  • 较长的regex优先
  • 默认规则为*

默认规则只能有一个。

SessionModel。它是一个存放在Session中的字段,用于记录Session中各个字段的生命周期数据,比如创建时间,最后更新时间等。它可以看成一个普通的session字段,因此可以配置匹配规则,放到指定的session容器中。

SessionModel可以转换成字符串,默认是转换成json,并作为普通的字段保存到session中。

<session-model-encoders>  <model-encoders:default-session-model-encoder />  <model-encoders:model-encoder class="..." />  <model-encoders:model-encoder class="..." /></session-model-encoders>

Session拦截器。框架提供了两个自带的拦截器:lifecycle-loggerattribute-whitelist,它们的用法在下面这个例子中已经非常清楚了。当然也可以定义自己的拦截器,有两种拦截器可以选择:

  • SessionLifecycleListener:监听Session的生成、销毁、访问事件。
  • SessionAttributeInterceptor:监听Session的读写事件。 框架会根据基类自动配置不同的拦截器。
    <request-contexts:interceptorsxmlns="http://www.alibaba.com/schema/services/request-contexts/session/interceptors"><lifecycle-logger /><attribute-whitelist>  <attribute name="_csrf_token" />  <attribute name="_lang" />  <attribute name="loginUser" type="com.alibaba...MyUser" />  <attribute name="shoppingCart" type="com.alibaba....ShoppingCart" /></attribute-whitelist><interceptor class="..." /></request-contexts:interceptors>

CookieStore。有些安全性要求不高的session字段不必保存在服务端,而是保存在浏览器端。这样对服务器的压力也会小一些。

Cookie中只能存放字符串,而session中可以存放java对象,因此对接cookie和session需要将Java对象转换成字符串。这种转换交给encoder进行。配置方法如下:

<session-stores:cookie-store>  ...  <session-stores:encoders>    <session-encoders:encoder class="..." />    <session-encoders:encoder class="..." />    <session-encoders:encoder class="..." />  </session-stores:encoders></session-stores:cookie-store>

可以指定多个encoder,写入session时,使用第一个encoder进行编码,读取session时,依次使用不同的解码器进行解码,直到正确解码为止。

框架自带了几个编码器,默认使用hessian进行编码。

<session-stores:encoders>  <session-encoders:serialization-encoder /></session-stores:encoders>

编码后加密。

<session-encoders:serialization-encoder>  <session-serializers:hessian-serializer />  <session-encrypters:aes-encrypter key="0123456789abcdef" /></session-encoders:serialization-encoder>

使用java原生序列化算法,这种算法的移植性最好。

<session-encoders:serialization-encoder>  <session-serializers:java-serializer /></session-encoders:serialization-encoder>

还有用于调试的内存SessionStore

<session-stores:simple-memory-store id="simple" />

每种SessionStore还可以设置加密、URLEncode、枚举映射、自定义映射等。

有两种CookieStore:单值和多值。

多值CookieStore,下面这个例子将session保存在tmp这个cookie中。由于cookie中的字段名称是可以重复的,因此有几个session就有几个tmp的cookie。

<session-stores:cookie-store id="temporaryClientStore">  <session-stores:cookie name="tmp" /></session-stores:cookie-store>

单值CookieStore。下面是最简单的例子:

<stores:single-valued-cookie-store id="loginNameCookie">  <stores:cookie name="login" /></stores:single-valued-cookie-store>