欢迎光临
我们一直在努力

b2b2c做子域名分离时关于session跨域的问题解决!

大家都知道session在不同域名中是获取的到,这就是为什么我们在一个域名登录另一个域名就掉线的原因,接下来我们就要解决session跨域的问题.

首先要了解session_id(),我们看下session_id是怎么解释?如下/

session_id()

session_id() 存取目前 session 代号。

语法: string session_id(string [id]);

本函数可取得或者重新配置目前存放 Session 的代号。若无参数 id 则表示只有取得目前 Session 的代号,加上参数则表示将 Session 代号设成新指定的 id。输入及返回均为字符串。

输出 session_id()

<?php
	session_start(); 
	echo session_id();
	// 输出 dqr58dnuqj2gufvg4o3tmjb9v4
?>

设置 session_id()

<?php
	session_id("NowaMagic");
	session_start(); 
	echo session_id();
	// 输出 NowaMagic
?>

session_id 恢复 session的内容

php的session是可以程序恢复的。session的恢复机制可以实现多个应用程序session的共享,因为php的 session都是以文件形式或者数据库存储的。首先是session_id的获取是通过session_id()函数获取,这个值可以进行传递。

程序恢复session,首先要知道session_id,大家通过手册可以知道session的恢复通过session_id($id);但是在恢复时 要注意一个先后顺序,要得到之前session的内容,必须在session_start()之前执行session_id($id),这样才能在执行了 session_start时初始化session的时候恢复到之前的内容,否则的话你得到的是一个空的session,你什么也得不到。之前 session被重新初始化了。这个和session_start()的作用有密切关系,因为session_start告诉php,session要初 始化,要从session文件中反序列化session内容,所以session_start的作用就是把之前存储的文件内容反序列化。 session_start序列化之前要知道session_id,如果没有就生成一个新的session_id。如果有就反序列化相应文件的内容。

接下来了了解cookie

cookie 字段定义

作用范围(Scope): path, domain

生命周期(Life cycle):也就是cookie的过期时间,expires (GMT,UTC) 时间标准

安全作用域(Security Scope):HttpOnly, Secure

跨域访问涉及 作用范围(Scope), 安全作用域(Security Scope)

如果 你不使用 js 操作 Cookie 的话,可以忽略 安全作用域(Security Scope)。

服务端只是 cookie 的接收者和解析者。由浏览器也就是客户端决定是否要将哪些 cookies 发送到到服务端。

是根据 cookie 的 path, 和 domain 来发送。

我们假设,我们现在有两个 domain.

  1. a.phpwindow.com
  2. www.phpwindow.com

如果想让 客户端将 www.phpwindow.com 下面的 cookie 也发送到 oauth2.phpwindow.com 下面。那么你需要,在 setcookie() 的时候,将 domain 设置成为 phpwindow.com

说这么多废话的意思就是,cookie能够解决跨子域存储的问题..

看完上面就应该知道关于php的session运行机制,我们做如下假设: 在a.phpwindow.com上保存一个session,我们存它的session_id在浏览器的cookie

,然后在b.phpwindow.com通过cookie获取到a保存在cookie的seesion_id,然后用session_id来恢复session的内容.则在b上我们就同样能得到session了.对,思路就是这样.

接下来打开项目找到以下路径pam/lib/account.php贴上我的修改代码,不想看的同学可以直接覆盖该文件即可.就能完美解决这个问题.

<?php
/**
 * ShopEx licence
 *
 * @copyright  Copyright (c) 2005-2010 ShopEx Technologies Inc. (http://www.shopex.cn)
 * @license  http://ecos.shopex.cn/ ShopEx License
 */
/**
* 该类是所有登录方式验证后写日志和SESSION的类
*/
class pam_account {

    public  $authType;
    /**
    * 构造方法
    * @param string $type 设置登录体系类型 shopadmin,member等
    */
    public function __construct($appId)
    {
        $this->objLibSession = kernel::single('base_session');
        $this->objLibSession->start();
        if( $appId )
        {
            $this->setAuthType($appId);
            $this->appId = $appId;
        }
        //setcookie("cross_id",'xxx',time()+3600,"/",".phpwidow.com");

        if( $this->getAttemptRemember() )
        {
            $this->setAttemptRememberExpires();
        }
    }

    public function setAuthType($appId)
    {
        $this->authType = $this->getAuthType($appId);

        return true;
    }
    
    
        //设置下次自动登录的session有效期为7天
    private function setAttemptRememberExpires()
    {
        $minute = 10080;//7天
        $this->objLibSession->set_sess_expires($minute);
        $this->objLibSession->set_cookie_expires($minute);
        return true;
    }
    //custom s 随机生成sessionid
    public function gen_session_id()
    {
        return sha1(uniqid('', true).request::getClientIp().str_random(25).microtime(true));
    }
    //custom e

    /**
     * 设置登录注册后的SESSION
     *
     * @param int $accountId 用户ID
     * @param string $account 用户名
     */
    public function setSession($accountId, $account)
    {
    
    
        if( $this->getAttemptRemember() )
        {
            $this->setAttemptRememberExpires();
        }
        //custom s 跨域
        
        $ssid=$this->gen_session_id();
    
        setCookie("cross_id",$ssid,time()+3600,"/",".phpwindow.com");
        $_COOKIE['cross_id'] = $ssid;
        
        //custom e
        $_SESSION['account'][$this->authType]['id'] = $accountId;
        $_SESSION['account'][$this->authType]['account'] = $account;
        
        //die('123');


        return true;
    }

    public function logout()
    {//die('fdsfsdf');
        
        
        //custom s
        
        setcookie("cross_id",'',time()-3600,"/");
        $_COOKIE['cross_id'] = '';
        //custom e
        //fb($_COOKIE);die;
        unset($_SESSION['account'][$this->authType]);
        return true;
    }

    public function getAttemptRemember()
    {
        session_id($_COOKIE['cross_id']);    
        session_start();  
        if( $_SESSION['account'][$this->authType]['remember'] == 'on' )
        {
            return true;
        }

        return false;
    }
    /**
     * @brief 设置当前登录是否为下次自动登录,自动登录有效期为7天
     *
     * @param $remember on 表示自动登录
     *
     * @return $this
     */
    public function setAttemptRemember($remember=null)
    {
        session_id($_COOKIE['cross_id']);    
        session_start();  
        if( $remember == 'on' )
        {
            $_SESSION['account'][$this->authType]['remember'] = 'on';
        }
        else
        {
            $_SESSION['account'][$this->authType]['remember'] = 'off';
        }
        return true;
    }

    /**
     * 返回登录ID
     */
    public function getAccountId()
    {     
        session_id($_COOKIE['cross_id']);    
        session_start();  
        return $_SESSION['account'][$this->authType]['id'];
    }

    /**
     * 返回登录账号
     */
    public function getLoginName()
    {
        session_id($_COOKIE['cross_id']);    
        session_start();  
        return $_SESSION['account'][$this->authType]['account'];
    }

    /**
     * 检查是否登录
     *
     * @return bool
     */
    public function check()
    {
        return $this->getAccountId($this->authType) ? true : false;
    }

    /**
     * 设置登录错误次数
     *
     * @param bool $isrest 是否重置错误次数
     *
     * @return bool
     */
    public function setLoginErrorCount($isreset=false)
    {
        
        session_id($_COOKIE['cross_id']);    
        session_start(); 
        
        if( $isreset )
        {
            $_SESSION['account'][$this->authType]['error_count'] = 0;
        }
        else
        {
            $_SESSION['account'][$this->authType]['error_count'] += 1;
        }

        return true;
    }

    /**
     * 返回当前登录错误次数
     */
    public function getLoginErrorCount()
    {
        session_id($_COOKIE['cross_id']);    
        session_start();  
        
        return $_SESSION['account'][$this->authType]['error_count'];
    }

    /**
    * 判断验证码是否开启
    *
    * @return bool 返回验证码开启状态
    */
    public function isEnableVcode($appId)
    {
        $this->appId = $appId;
        if( !class_exists($this->appId.'_service_vcode') )
        {
            return false;
        }
        else
        {
            $objLibServiceVcode = kernel::single($this->appId.'_service_vcode');
        }

        return $objLibServiceVcode->status();
    }

    /**
    * 安装时,注册体系类型
    * @access public
    * @param string $app_id appid
    * @param string $type 传入的体系的值
    * @param string $name 体系名称
    */
    public function registerAuthType($appId, $type, $name)
    {
        $accountTypes = app::get('pam')->getConf('account_type');
        $accountTypes[$appId] = array('name' => $name, 'type' => $type);
        app::get('pam')->setConf('account_type',$accountTypes);
        return true;
    }

    /**
    * 注销体系类型
    * @access public
    * @param string $appId appid
    */
    public function unregisterAuthType($appId)
    {
        $accountTypes = app::get('pam')->getConf('account_type');
        unset($accountTypes[$appId]);
        app::get('pam')->setConf('account_type',$accountTypes);
        return true;
    }

    /**
    * 返回体系类型
    * @access public
    * @param string $app_id appid
    * @return string 返回体系字符串
    */
    public function getAuthType($appId='desktop')
    {
        $aType = app::get('pam')->getConf('account_type');
        return $aType[$appId]['type'];
    }//End Function
}

未经允许不得转载:PHP之窗 » b2b2c做子域名分离时关于session跨域的问题解决!

分享到:更多 ()

评论 3

  • (必填)
  • 6 + 15 = ?(必填)
  1. #2

    提前祝您新年快乐。
    乙未年(羊)冬月十九 2015-12-29

    yiluyingxiao2年前 (2015-12-29)回复
    • gg

      suckers2年前 (2016-09-14)回复
  2. #1

    Happy New Year.

    wo2年前 (2016-01-01)回复

产品与解决方案,顶尖的服务!!

联系我们