解决方案 »

  1.   

    SESSIONID就是存在cookie中吧...当前域的请求都会挂着cookie值一起发送
      

  2.   

    服务器端是存在redis中的,呢么现在发送请求是不是将sessionid存世cookie中就行了啊?
      

  3.   

    服务器端是存在redis中的,呢么现在发送请求是不是将sessionid存世cookie中就行了啊?

    服务器初次创建session的时候后返回session到客服端(在返回头中有setCookie),浏览器会把sessionname->sessionid存到cooike中,同path下再次请求服务器时,会自动在请求头中带上cooike信息,服务器可以在_COOKIE中得取到想要的session
      

  4.   

    SESSION需要COOKIE的支持,在客户端与服务端进行SESSION处理时,实际上是客户端的COOKIE保存了SESSIONID,然后将SESSIONID发给服务端,这样服务端才知道使用哪个SESSION。
    如你所言,你的SESSION在服务器端现在是用REDIS存储的,那么key应该以SESSIONID来命名啊,这样客户端将SESSIONID发送至服务器后,服务端获取这个SESSIONID,然后再去REDIS里找key为SESSIONID的那条记录。
      

  5.   

    因为现在做的是一个手机端的接口,客户端发送请求的地址是abc/aaa.php?controller=aaa&action=bbb&sess={session id}
    还有 REDIS中存储sessinid是用md5($_SESSION['userid'])为key存储的。
      我现在该怎么做才能共享session呢?
      

  6.   

    服务器端是存在redis中的,呢么现在发送请求是不是将sessionid存世cookie中就行了啊?

    服务器初次创建session的时候后返回session到客服端(在返回头中有setCookie),浏览器会把sessionname->sessionid存到cooike中,同path下再次请求服务器时,会自动在请求头中带上cooike信息,服务器可以在_COOKIE中得取到想要的session
    客户端发送请求的地址是abc/aaa.php?controller=aaa&action=bbb&sess={session id}  是url的形式传参的,我现在怎么才能共享session呢?
      

  7.   

    session_id($_GET['sess']);
    session_start();
      

  8.   

    因为现在做的是一个手机端的接口,客户端发送请求的地址是abc/aaa.php?controller=aaa&action=bbb&sess={session id}
    还有 REDIS中存储sessinid是用md5($_SESSION['userid'])为key存储的。
      我现在该怎么做才能共享session呢?客户端请求URL中的传参sess就是SESSIONID值(此值通过 session_id() 函数生成),服务端GET获取此传参,然后设置sessionid为GET到的sess,然后就能调用对应SESSION中的userid,然后再去redis中查询。大致如:
    session_id($_GET['sess']);
    session_start();
    $key=md5($_SESSION['userid']);
    echo $redis->get($key);
      

  9.   

    你用redis存,自然是存在内存里! $sessionID = $_GET['sess'];
    /*
           这里判断获取的$sessionID与redis里面的相不相等
    */
    if('相等') {
        session_id($_GET['sess']);
        session_start();
    } else {
        '不存在id为' . $sessionID . '的session';
    }
      

  10.   

    基于redis写的session存储class memsession
    {
    /*
     * Session基本配置
     */
    private $sSessionID = ''; //session 唯一标志
    private $sSessionPrefix = 'sess_'; //session 标志前缀 
    private $iExpireTime = 1800; //session 缓存过期时间,单位秒,默认30分钟
    private $sCookieName = '_sessionHandler'; //SESSION 的Cookie名称

    /*
     * Cookie 基本设置
     */
    private $sCookieDomain = ''; //Cookie 域名信息
    private $sCookiePath = '/'; //Cookie 文件位置
    private $iCookieExpireTime = 0; //SESSION 的Cookie过期时间
    private $bCookieSecure = FALSE; //是否可以通过HTTPS安全传递cookie
    /*
     * Memcache 配置
     */
    private $aMemcacheConfig = array(); //memcache 主机配置
    public $oMemcache = NULL; //memcache 实例

    /*
     * 在线用户
     */
    private $aOnlineUser = array(); //在线用户列表
    private $sOnlineMD5 = ''; //在线用户MD5值,用于判断在线用户是否改变
    private $aUserInfo = array( //session共享时统一的用户信息变量命名
    'id' => 'userid',
    'name' => 'username',
    );

    /*
     * 安全机制设置
     */
    private $sIp = ''; //客户端IP限制 
    private $sCodeKey = "N!c7^G)3*A(hy?szvs@,n+";//替换ip的安全机制
    /*
     * 其他调试参数
     */
    private $bDevelopMode = FALSE; //开发模式,用于记录和显示相关错误信息

    /**
     * 构造函数(是否实例化的时候启动session)
     * 
     * @access public
     * @param string $sSessionID -Session ID,缺省是空,新创建一个Session ID。
     * @param int $iExpireTime - Session失效时间,缺省是0,当浏览器关闭的时候失效, 该值单位是秒
     */
    function __construct( $iExpireTime=0, $sSessionID='' )
    {
    //载入全局session配置
    if( FALSE != ($temp = A::getIni("class.memsession.sessionConfig")) )
    {
    if( is_array($temp) )
    {
    $this->sSessionPrefix = isset($temp['sessionPrefix']) ? $temp['sessionPrefix'] : 'sess_';
    $this->iExpireTime = isset($temp['sessionExpireTime']) ?
    intval($temp['sessionExpireTime']) : 1800;
    $this->sCookieName = isset($temp['sessionCookieName']) ?
    $temp['sessionCookieName'] : '_sessionHandler';
    $this->aMemcacheConfig = isset($temp['memcacheConfig']) ? (array)$temp['memcacheConfig'] : array();

    }
    else
    {
    $this->iExpireTime = 1800;
    $this->sSessionPrefix = 'sess_';
    $this->sCookieName = '_sessionHandler';
    $this->aMemcacheConfig = array();
    }
    unset( $temp );
    }
    else
    {
    $this->iExpireTime = 1800;
    $this->sSessionPrefix = 'sess_';
    $this->sCookieName = '_sessionHandler';
    $this->aMemcacheConfig = array();
    }

    //载入全局cookie设置
    if( FALSE != ($temp = A::getIni("cookieConfig")) )
    {
    if( is_array($temp) )
    {
    if( isset($temp['expire']) && (bool)intval($temp['expire']) )
    {
    $this->iCookieExpireTime = CURRENT_TIMESTAMP+intval($temp['expire']);
    }
    else 
    {
    $this->iCookieExpireTime = 0;
    }
    $this->sCookieDomain = isset($temp['domain']) ? $temp['domain'] : '';
    $this->sCookiePath = isset($temp['path']) ? $temp['path'] : '/';
    $this->bCookieSecure = isset($temp['secure']) ? (bool)$temp['secure'] : FALSE;
    }
    else
    {
    $this->sCookieDomain = '';
    $this->sCookiePath = '/';
    $this->iCookieExpireTime= 0;
    $this->bCookieSecure = FALSE;
    }
    unset( $temp );
    }
    else
    {
    $this->sCookieDomain = '';
    $this->sCookiePath = '/';
    $this->iCookieExpireTime= 0;
    $this->bCookieSecure = FALSE;
    }
    $this->iCookieExpireTime= intval($iExpireTime)>0 ? CURRENT_TIMESTAMP+intval($iExpireTime) : $this->iCookieExpireTime; $this->sIp = getRealIP();
    //从cookie中读取sessionID值或者指定Session ID值
    if( $sSessionID == '' && !empty($_COOKIE[$this->sCookieName]) )
    {
    $this->sSessionID = $_COOKIE[$this->sCookieName];
    }
    else
    {
    $this->sSessionID = $sSessionID;
    }
    //如果从cookie里获取或者指定了Session ID,则验证session ID的合法性
    if( $this->sSessionID )
    {
    $temp_sessionID = substr( $this->sSessionID, 0, 32 );
    if( $this->getValidCode($temp_sessionID) == substr($this->sSessionID,32) )
    {
    $this->sSessionID = $temp_sessionID;
    }
    else
    {
    $this->sSessionID = '';
    }
    }
    //如果存在指定 Session ID的值,则读取该ID下保存的Session数组集合
    if( $this->sSessionID )
    {
    $this->getSession();
    }
    else 
    {//如果不存在则新开始一个session
    $this->createSessionID();
    setcookie( $this->sCookieName, $this->sSessionID.$this->getValidCode($this->sSessionID),
       $this->iCookieExpireTime, $this->sCookiePath, 
       $this->sCookieDomain, $this->bCookieSecure );
    $GLOBALS['_SESSION'] = array();
    $this->setSession();
    }

    //给一直在线活跃的用户延长session过期时间
    register_shutdown_function(array(&$this, 'closeSession'));
    }

    /*
     * 析构函数
     */
    function __destruct()
    {
    if( $this->oMemcache )
    {//如果memcache连接实例存在则注销
    $this->oMemcache = NULL;
    }
    unset($this->aMemcacheConfig);
    }

    /**
     * 注册一个session变量
     * 
     * @access public
     * @param String $sName 变量名
     * @param String $sValue 变量值
     * @return boolean 如果变量已经存在且值相同则返回false,值不相同则替换,成功返回true
     */
    public function register( $sName, $sValue )
    {
    if( isset($GLOBALS['_SESSION'][$sName]) && $GLOBALS['_SESSION'][$sName] == $sValue )
    {//变量已经存在而且值相同
    return FALSE;
    }
    $GLOBALS['_SESSION'][$sName] = $sValue;
    $this->setSession();
    return TRUE;
    }

    /**
     * 销毁一个已经注册的变量
     * 
     * @access public
     * @param String $sName 要销毁的变量名
     * @return boolean 成功返回true,失败返回false
     */
    public function unregister( $sName )
    {
    if( isset($GLOBALS['_SESSION'][$sName]) )
    {
    unset( $GLOBALS['_SESSION'][$sName] );
    $this->setSession();
    }
    return TRUE;
    }

    /**
     * 获取一个已经注册的变量
     * 
     * @access public
     * @param String $sName 要获取的变量名,如果为空则获取所有的
     * @return unknow 获取的变量值
     */
    public function get( $sName='' )
    {
    if( $sName=='' )
    {
    return $GLOBALS['_SESSION'];
    }
    else
    {
    if( !isset($GLOBALS['_SESSION'][$sName]) )
    {
    return FALSE;
    }
    return $GLOBALS['_SESSION'][$sName];
    }
    }

    /**
     * 获取所有在线用户列表
     * 
     * @access public
     * @return array 在线用户列表
     */
    public function getOnlineUsers()
    {
    if( empty($this->sOnlineMD5) )
    {//如果未读出所有在线用户列表,则先读出用户列表
    $this->_getAllOnlineUser();
    }
    return $this->aOnlineUser;
    }

    /**
     * 根据用户ID判断某个用户是否在线,如果不在返回FALSE,在线返回TRUE
     * 
     * @access  public
     * @param  int $iUserID //用户ID
     * @return boolean //不在返回FALSE,在线返回TRUE
     */
    public function isOnline( $iUserID )
    {
    $iUserID = intval( $iUserID );
    if( empty($this->sOnlineMD5) )
    {//如果未读出所有在线用户列表,则先读出用户列表
    $this->_getAllOnlineUser();
    }
    if( empty($this->aOnlineUser) )
    {//如果在线用户列表为空,则直接返回TRUE,跳过数组搜索,提高效率
    return FALSE;
    }
    if( !array_key_exists($iUserID,$this->aOnlineUser) )
    {//如果不存在给定用户
    return FALSE;
    }
    return TRUE;
    }
      

  11.   


    /** * 根据用户ID获取在线信息
     * 
     * @access  public
     * @param  int $iUserID //用户ID
     * @return  [mixd] //如果存在则返回用户信息数组,否则返回FALSE;
     */
    public function getOnlineInfo( $iUserID )
    {
    if( !$this->isOnline($iUserID) )
    {
    return FALSE;
    }
    return $this->aOnlineUser[$iUserID];
    }

    /**
     * 根据用户ID,把该用户从线上踢掉
     * 
     * @access public
     * @param  int $iUserID //用户ID
     * @return boolean //成功返回TRUE,失败返回FALSE
     */
    public function outOnline( $iUserID )
    {
    if( FALSE != ($temp_info = $this->getOnlineInfo($iUserID)) )
    {
    return $this->destroy( $temp_info['sessionID'],$temp_info[$this->aUserInfo['id']] );
    }
    return TRUE;
    }
    /**
     * 检查memcache的实例是否存在,如果不存在则创建
     * @access private
     * @return boolean 成功或者失败
     */
    private function checkMemcache()
    {
    //如果不支持memcache扩展,或者没有安装memcache扩展则报错
    if( !class_exists('memcachedb') )
    {
    $temp_message = "Failed: Memcache extension not install";
    //日志记录操作,只有打开日志功能才记录
    if( (bool)(intval(A::getIni('error/trigger_error')) & APPLE_ON_ERROR_LOG) )
    {
    $GLOBALS['oLogs']->addDebug( $temp_message, "memsessionError" );
    }
    //调试模式检查,只有开启了开发模式的调试才能打印
    if( $this->bDevelopMode )
    {
    A::halt( " From Class.memcacheSession.Exception: [" . $temp_message . "]" );
    }
    return FALSE;
    }
    //如果实例已经存在则直接返回
    if( $this->oMemcache && is_object($this->oMemcache) )
    {
    return TRUE;
    }
    //新建实例
    $this->oMemcache = new memcachedb( $this->aMemcacheConfig );
    return TRUE;
    }

    /**
     * 获取Session ID
     * 
     * @access public
     * @return Sting
     */
    public function getSessionID()
    {
    return $this->sSessionID;
    }

    /**
     * 生成一个Session ID
     * 
     * @access private
     * @return String 
     */
    private function createSessionID()
    {
    $this->sSessionID = md5( uniqid(mt_rand(), TRUE) );
    return $this->sSessionID;
    }

    /**
     * 通过客户端IP段和浏览器信息加强session安全性。
     * 
     * @access private
     * @param String $sSessionID 指定的session ID
     * @return String 返回检验码
     */
    private function getValidCode( $sSessionID )
    {
    static $ip='';
    if( $ip == '' )
    {
    //$ip = substr( $this->sIp, 0, strrpos($this->sIp,'.') );
                            $ip = $this->sCodeKey;//去掉ip校验
    }
    $temp_string = !empty( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] . $ip . $sSessionID : $ip . $sSessionID;
    return sprintf( "%08x", crc32($temp_string) );
    }

    /**
     * 获取已经存储在memcache上面的session Key
     * 
     * @access private
     * @param String $sessionID 指定一个session ID
     * @return String $sessionKey
     */
    private function getSessionKey( $sSessionID='' )
    {
                    $isAdmin    =   !empty($GLOBALS['isadmin']) && $GLOBALS['isadmin']==1 ? 1 : 0;
    $sessionKey = $sSessionID == '' ? $this->sSessionPrefix . $this->sSessionID.$isAdmin : $sSessionID;
    return $sessionKey;
    }

    /**
     * 获取所有在线用户列表
     * 
     * @access public
     * @return boolean
     */
    private function _getAllOnlineUser()
    {
    if( !empty($this->sOnlineMD5) )
    {//如果已经读出了所有在线用户列表,则直接返回
    return TRUE;
    }
    $this->checkMemcache();
    $temp_onlineUser = $this->oMemcache->getOne( '__OnlineUser' );
    if( !is_array($temp_onlineUser) || empty($temp_onlineUser) )
    {
    $this->aOnlineUser = array();
    $this->sOnlineMD5 = md5( serialize($this->aOnlineUser) );
    }
    else
    {
    $this->aOnlineUser = $temp_onlineUser;
    $this->sOnlineMD5 = md5( serialize($this->aOnlineUser) );
    //对过期的用户进行清理
    foreach( $this->aOnlineUser as $key=>$val )
    {
    $temp_expireTime = intval($val['time']) + intval($val['expire']);
    if( $temp_expireTime < CURRENT_TIMESTAMP )
    {//如果过期则删除
    unset( $this->aOnlineUser[$key] );
    }
    }
    unset( $temp_expireTime );
    if( $this->sOnlineMD5 != md5(serialize($this->aOnlineUser)) )
    {//如果数据发生了改变,则回存
    $this->sOnlineMD5 = md5( serialize($this->aOnlineUser) );
    $this->_saveOnlineUser();
    }
    }
    unset($temp_onlineUser);
    return $this->aOnlineUser;
    }

    /**
     * 读取session的值
     * 
     * @access private
     * @return void
     */
    private function getSession()
    {
    $this->checkMemcache();
    $sessionKey = $this->getSessionKey();
    $session = $this->oMemcache->getOne( $sessionKey );
    //如果指定的session不存在则创建
    if( !is_array($session) || empty($session) )
    {
    $GLOBALS['_SESSION'] = array();
    $this->setSession();
    }
    else
    {
    $GLOBALS['_SESSION'] = $session;
    }
    unset( $session );

    }


    /**
     * 保存当前的session值到memcache
     * 
     * @access private
     * @param String $sSessionID
     * @return boolean 成功或者失败 
     */
    private function setSession()
    {
    $this->checkMemcache();
    $sessionKey = $this->getSessionKey();
    if( empty($GLOBALS['_SESSION']) )
    {//如果全局函数中的session值为空,则在memcache中重新建立或者设置为空
    $temp_ret = $this->oMemcache->insert( $sessionKey, $GLOBALS['_SESSION'], $this->iExpireTime );
    }
    else 
    {//如果全局函数中session的值不为空,则替换memcache中的值
    $temp_ret = $this->oMemcache->update( $sessionKey, $GLOBALS['_SESSION'], $this->iExpireTime );
    //记录前台登录用户的ID对应的sessionKey值
                            $this->setUserSessionKey();
    /*
     * 如果存在用户登陆信息,则更新用户在线列表
     */
    $id  = $this->aUserInfo['id'];
    $name  = $this->aUserInfo['name'];
    if( isset( $GLOBALS['_SESSION'][$id] ) )
    {
    $GLOBALS['_SESSION'][$name] = isset($GLOBALS['_SESSION'][$name]) ? $GLOBALS['_SESSION'][$name] : '';
    //如果在线用户列表存在该用户信息
    if( FALSE != ($temp_info = $this->getOnlineInfo($GLOBALS['_SESSION'][$id])) )
    {
    if( $temp_info[$name] != $GLOBALS['_SESSION'][$name] ||
    $temp_info['sessionID'] != $this->sSessionID ||
    $temp_info['ip'] != $this->sIp ||
    $temp_info['expire'] != $this->iExpireTime ||
    (intval($temp_info['time'])+10) < CURRENT_TIMESTAMP )
    {//如果用户信息改变或者两次保存间隔时间大于10秒,则重新保存
    $this->aOnlineUser[$GLOBALS['_SESSION'][$id]][$name] = $GLOBALS['_SESSION'][$name];
    $this->aOnlineUser[$GLOBALS['_SESSION'][$id]]['sessionID'] = $this->sSessionID;
    $this->aOnlineUser[$GLOBALS['_SESSION'][$id]]['ip'] = $this->sIp;
    $this->aOnlineUser[$GLOBALS['_SESSION'][$id]]['expire'] = $this->iExpireTime;
    $this->aOnlineUser[$GLOBALS['_SESSION'][$id]]['time']  = CURRENT_TIMESTAMP;
    $this->_saveOnlineUser();
    }
    unset( $temp_info );
    }
    else 
    {
    //重组用户信息
    $temp_userInfo = array();
    $temp_userInfo[$id] = $GLOBALS['_SESSION'][$id];
    $temp_userInfo[$name] = $GLOBALS['_SESSION'][$name];
    $temp_userInfo['sessionID'] = $this->sSessionID;
    $temp_userInfo['ip'] = $this->sIp;
    $temp_userInfo['time'] = CURRENT_TIMESTAMP;
    $temp_userInfo['expire'] = $this->iExpireTime;
    //加入在线列表
    $this->aOnlineUser[$GLOBALS['_SESSION'][$id]] = $temp_userInfo;
    unset( $temp_userInfo );
    $this->_saveOnlineUser();
    }
    }//更新用户在线列表结束
    unset( $id );
    unset( $name );
    }
    //如果保存session失败则根据相关设置写入日志或者打印调试信息
    if( !$temp_ret )
    {
    $temp_message = "Failed: Save sessiont data failed, please check memcache server";
    //日志记录操作,只有打开日志功能才记录
    if( (bool)(intval(A::getIni('error/trigger_error')) & APPLE_ON_ERROR_LOG) )
    {
    $GLOBALS['oLogs']->addDebug( $temp_message, "memsessionError" );
    }
    //调试模式检查,只有开启了开发模式的调试才能打印
    if( $this->bDevelopMode )
    {
    A::halt( " From Class.memcacheSession.Exception: [" . $temp_message . "]" );
    }
    return FALSE;
    }
    return TRUE;
    }

    /**
     * 回调函数,用于对一直在线的用户自动延长过期时间
     * 
     * @access public
     * @return boolean 成功与否
     */
    public function closeSession()
    {
    return $this->setSession();
    }

    /**
     * 销毁某个sessionID下所有已注册的seesion变量
     * 
     * @access public
     * @param string $sSessionID //要注销的session ID
     * @param  int $iUserID //要销毁的user ID,如果有的话则从在线列表里删除
     * @return void
     */
    public function destroy( $sSessionID='', $iUserID=0 )
    {
    //从memcache删除已经注册的seesion值
    $this->checkMemcache();
    $sessionKey = $this->getSessionKey( $sSessionID );
    $this->oMemcache->delete( $sessionKey );
    $iUserID = intval($iUserID);
    //如果注销自己的则清空全局session值,并设置cookie过期
    if( $sSessionID == '' || $sSessionID == $this->sSessionID )
    {
    if( isset($GLOBALS['_SESSION'][$this->aUserInfo['id']]) )
    {
    $iUserID = intval($GLOBALS['_SESSION'][$this->aUserInfo['id']]);
    }
    else
    {
    $iUserID = 0;
    }
    $GLOBALS['_SESSION'] = array();
    //设置cookie过期
    setcookie( $this->sCookieName, $this->sSessionID, 1, 
    $this->sCookiePath, $this->sCookieDomain, $this->bCookieSecure );
    }
    //把用户从在线列表里删除
    $this->_deleteOnline( $iUserID );
    }

    /**
     * 根据用户的 ID 把用户从在线列表里删除
     * 
     * @access private
     * @param  int $iUserID //用户 ID
     * @return boolean  成功返回TRUE,失败返回FALSE
     */
    private function _deleteOnline( $iUserID=0 )
    {
    $iUserID = intval( $iUserID );
    if( $this->isOnline($iUserID) )
    {
    unset($this->aOnlineUser[$iUserID]);
    }
    if( $this->_saveOnlineUser() )
    {
    return TRUE;
    }
    return FALSE;
    }
      

  12.   


    /**
     * 回存用户在线列表
     * 
     * @access private
     * @return boolean 成功返回TRUE,失败返回FALSE
     */
    private function _saveOnlineUser()
    {
    $this->checkMemcache();
    if( $this->sOnlineMD5 == md5(serialize($this->aOnlineUser)) )
    {//如果数据没有发生改变则直接返回
    return TRUE;
    }
    $temp_ret = $this->oMemcache->insert( '__OnlineUser', $this->aOnlineUser );
    //如果保存session失败则根据相关设置写入日志或者打印调试信息
    if( !$temp_ret )
    {
    $temp_message = "Failed: Save Onlineuser data failed, please check memcache server";
    //日志记录操作,只有打开日志功能才记录
    if( (bool)(intval(A::getIni('error/trigger_error')) & APPLE_ON_ERROR_LOG) )
    {
    $GLOBALS['oLogs']->addDebug( $temp_message, "memsessionError" );
    }
    //调试模式检查,只有开启了开发模式的调试才能打印
    if( $this->bDevelopMode )
    {
    A::halt( " From Class.memcacheSession.Exception: [" . $temp_message . "]" );
    }
    return FALSE;
    }
    unset( $temp_ret );
    return TRUE;
    }
            
            /**
     * 存储当前登录用ID对应的sessionkey
     * 
     * @access private
     */
            private function setUserSessionKey(){
                if(empty($GLOBALS['isadmin']) && $_SESSION['userid']){
                    $this->checkMemcache();
                    $this->oMemcache->insert(md5($_SESSION['userid']), $this->getSessionKey(), $this->iExpireTime);
                }elseif($GLOBALS['isadmin'] && $_SESSION["adminname"]){
                    //管理员的以用户名来单独控制
                    $this->checkMemcache();
                    $this->oMemcache->insert(md5($_SESSION["adminname"]), $this->getSessionKey(), $this->iExpireTime);
                }
            }
    }