分布式session的共享及cookie跨域共享

 本文将简单介绍一下分布式环境下session共享问题、跨域名来共享cookie及多终端session的统一。

一:分布式session的共享
既然是一个分布式 Session的处理框架,必然会重新实现 HttpSession的操作接口,使得应用操作 Session的对象都是我们实
现的 InnerHttpSession对象,这个操作必须在进入应用之前完成,所以可以配置一个 filter拦截用户的请求。
先看一下如何封装 Httpsession对象和拦截请求,下图是时序图。

 

我们可以在应用的web.xml中配置一个SessionFilter,用于在请求到达MVC框架之前封装Httpservletrequest和HttpservletResponse
对象,并创建我们自己的 InnerHttpSession对象,把它设置到 request和 response对象中。这样应用系统通过request.getHttpSession()
返回的就是我们创建的 InnerHttpSession对象了,我们可以拦截 response的 addCookies设置的Cookie。在时序图中,应用创建的所有Session对象都会保存在InnerHttpSession对象中,当用户的这次访问请求完成时,Session框架会把这个InnerHttpSession的所有内容再更新到分布式缓存中,以便于这个用户通过其他服务器再次访问这个应用系统。另外,为了保证一些应用
对session稳定性的要求,可以将一些非常关键的session再存储到cookie中,如当分布式出现问题时,可以将部分session存储到cookie中去,这样即使分布式缓存出现问题也不会影响关键业务的运行。

二:如何跨域共享Cookie
还有一个非常重要的问题就是如何处理跨域名来共享cookie的问题。我们知道cookie是有域名限制的,即在一个域名下的cookie不能被另一个域名访问,所以如何在一个域名下登陆已经成功,如何访问到另一个域名的应用确保登录状态仍然有效,对于这个问题大型互联网项目经常遇到。如何解决这个问题呢?下面介绍一种解决方案。
 

 

从图中可以看出,要实现 Session同步,需要另外一个跳转应用,这个应用可以被个或者多个域名访问,它的主要功能是一个域名下取得 sessionid,然后将这个 sessionid同步到另外一个域名下。这个 sessionid其实就是一个 Cookie,相当于我们经常遇到的JSESSIONID,所以要实现两个域名下的 Session同步,必须要将同一个 sessionid作为Cookie写到两个域名下。
三:多终端session统一
 在无线端发展初期,后端的服务系统未必和PC的服务系统是统一的,这样就涉及在一端调用多个系统时如何做到服务端
Session共享的问题了。有两个明显的例子:一个是在无线端可能会通过手机访问无线服务端系统,同时也会访问PC端的服务
系统,如果它们两个的登录系统没有统一的话,将会非常麻烦,可能会出现二次登录的情况:另一个是在手机上登录以后再在
PC上同样访问服务端数据,Session能否共享就决定了客户端是否要再次登录。
针对这两种情况,目前都有理想的解决方案:  
 1) 多端共享 Session
 多端共享 Session必须要做的工作是不管是无线端还是PC端,后端的服务系统必须统一会话架构,也就是两边的登录系统
必须要基于一致的会员数据结构、 Cookie与 Session的统一。也就是不管是PC端登录还是无线端登录,后面对应的数据结构和
存储要统写到客户端的 Cookie也必须一样,这是前提条件。如何实现这一点呢?就是上文说到的分布式session架构。

 

上面服务端统一 Session后,在同一个终端上不管是访问哪个服务端都能做到登录状态统一。例如不管是 Native还是内嵌Webview,都可以拿统一的 Session ID去服务端验证登录状态
2) 多终端登录
目前很多网站都会出现无线端和PC端多端登录的情况,例如可以通过扫码登录等,这些是如何实现的呢?其实比较简单,如下图所示:


这里手机端在扫码之前必须是己经登录的状态,因为这样才能获取到底是谁将要登录的信息,同时扫码的二维码也带有一个特定的标识,标识是这个客户端通过手机端登录了当手机端扫码成功后,会在服务端设置这个二维码对应的标识为已经登录成功,这时PC客户端会通过将“心跳”请求发送到服务端,来验证是否已经登录成功,这样就成为一种便捷的登录方式。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
class Session { //mysql的主机地址 const db_host = "localhost"; //需要第三方指定ip地址 //数据库用户名 const db_user = "root"; //需要第三方指定自己的用户名 //数据库密码 const db_pwd = ""; //需要第三方指定自己的库据库密码 //数据库 const db_name = "thinkphp"; //需要第三方指定数据库 //数据库表 const db_table = "tbl_session"; //需要第三方指定数据表 //mysql-handle private $db_handle; //session-lifetime private $lifeTime; function open($savePath, $sessName) { // get session-lifetime $this--->lifeTime = get_cfg_var("session.gc_maxlifetime"); // open database-connection $db_handle = @mysql_connect(self::db_host, self::db_user, self::db_pwd); $dbSel = @mysql_select_db(self::db_name, $db_handle); // return success if(!$db_handle || !$dbSel) return false; $this->db_handle = $db_handle; return true; } function close() { $this->gc(ini_get('session.gc_maxlifetime')); // close database-connection return @mysql_close($this->db_handle); } function read($sessID) { // fetch session-data $res = @mysql_query("SELECT session_data AS d FROM ".self::db_table." WHERE session_id = '$sessID' AND session_expires > ".time(), $this->db_handle); // return data or an empty string at failure if($row = @mysql_fetch_assoc($res)) return $row['d']; return ""; } function write($sessID, $sessData) { // new session-expire-time $newExp = time() + $this->lifeTime; // is a session with this id in the database? $res = @mysql_query("SELECT * FROM ".self::db_table." WHERE session_id = '$sessID'", $this->db_handle); // if yes, if(@mysql_num_rows($res)) { // ...update session-data @mysql_query("UPDATE ".self::db_table." SET session_expires = '$newExp', session_data = '$sessData' WHERE session_id = '$sessID'", $this->db_handle); // if something happened, return true if(@mysql_affected_rows($this->db_handle)) return true; } else // if no session-data was found, { // create a new row @mysql_query("INSERT INTO ".self::db_table." ( session_id, session_expires, session_data) VALUES( '$sessID', '$newExp', '$sessData')", $this->db_handle); // if row was created, return true if(@mysql_affected_rows($this->db_handle)) return true; } // an unknown error occured return false; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值