You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从CodeIgniter 4跳转并登录到CodeIgniter 3指定页面?

解决CI4统一登录跳转CI3后台的会话同步问题

问题核心

你当前的代码直接跳转CI3仪表盘,但CI4和CI3的会话机制完全独立:两者的会话存储路径、加密规则、会话ID生成逻辑都不兼容,所以CI4设置的会话CI3根本读不到,导致跳转后处于未登录状态。

可行解决方案

方案1:临时令牌验证(推荐,安全可控)

通过生成一次性临时令牌,让CI3验证令牌后自动创建会话,步骤如下:

1. 新增令牌存储表

在共用数据库里新建login_tokens表:

CREATE TABLE login_tokens (
    id INT AUTO_INCREMENT PRIMARY KEY,
    token VARCHAR(64) NOT NULL UNIQUE,
    user_id INT NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    expires_at DATETIME NOT NULL,
    used TINYINT(1) DEFAULT 0,
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);

2. 修改CI4登录控制器逻辑

验证用户密码通过后,生成令牌并存入数据库,再跳转CI3时携带令牌:

// 原密码验证通过后的逻辑
if($password == $pass)
{
    $ses_data = [
        'admin_id'      => $data['user_id'],
        'user_name'     => $data['user_name'],
        'e_mail'        => $data['e_mail'],
        'userType'      => $data['user_type'],
        'user_state'    => $userstate,
        'logged_in'     => TRUE
    ];
    $this->session->set($ses_data);         
    
    if($data['user_type'] == 'admin' || $data['user_type'] == 'state user')
    {
        if($userstate != "MA")
        {
            return redirect()->to($userstate);
        }else{
            // 生成临时令牌
            $token = bin2hex(random_bytes(32)); // 生成64位随机令牌
            $expiresAt = date('Y-m-d H:i:s', strtotime('+5 minutes')); // 5分钟过期
            
            // 存入数据库
            $this->db->table('login_tokens')->insert([
                'token' => $token,
                'user_id' => $data['user_id'],
                'expires_at' => $expiresAt
            ]);
            
            // 跳转CI3并携带令牌
            return redirect()->to("http://localhost/CI3/dashboard?token={$token}");
        }
    }   
}

3. 修改CI3 Dashboard控制器

在CI3的Dashboard控制器的index方法开头,添加令牌验证逻辑:

public function index()
{
    // 检查令牌参数
    if($this->input->get('token'))
    {
        $token = $this->input->get('token');
        
        // 验证令牌:存在、未过期、未使用
        $tokenData = $this->db->get_where('login_tokens', [
            'token' => $token,
            'expires_at >' => date('Y-m-d H:i:s'),
            'used' => 0
        ])->row();
        
        if($tokenData)
        {
            // 获取用户信息
            $user = $this->db->get_where('users', ['user_id' => $tokenData->user_id])->row();
            
            if($user)
            {
                // 设置CI3会话
                $ses_data = [
                    'admin_id'      => $user->user_id,
                    'user_name'     => $user->user_name,
                    'e_mail'        => $user->e_mail,
                    'userType'      => $user->user_type,
                    'user_state'    => 'MA',
                    'logged_in'     => TRUE
                ];
                $this->session->set_userdata($ses_data);
                
                // 标记令牌已使用
                $this->db->where('id', $tokenData->id)->update('login_tokens', ['used' => 1]);
            }
        }
    }
    
    // 检查是否已登录,未登录则跳转到CI3登录页
    if(!$this->session->userdata('logged_in'))
    {
        redirect('login');
    }
    
    // 原Dashboard逻辑...
    $this->load->view('dashboard');
}

方案2:共享会话存储(适合有Redis环境的场景)

如果服务器有Redis,可以让CI4和CI3共用Redis存储会话,确保两者的会话配置一致:

  1. CI4配置:修改app/Config/Session.php,设置Redis驱动:
public $driver = 'redis';
public $redisHost = '127.0.0.1';
public $redisPort = 6379;
public $redisPassword = '';
public $redisDatabase = 0;
public $cookieName = 'ci_session'; // 和CI3保持一致
public $encryptionKey = '你的加密密钥'; // 和CI3的encryption_key一致
  1. CI3配置:修改application/config/config.php:
$config['sess_driver'] = 'redis';
$config['sess_save_path'] = 'tcp://127.0.0.1:6379';
$config['sess_cookie_name'] = 'ci_session'; // 和CI4一致
$config['encryption_key'] = '你的加密密钥'; // 和CI4一致
  1. 调整CI4的会话数据键名,让CI3能识别:CI3的会话数据存在_ci_data数组里,所以CI4设置会话时需要兼容这个结构,或者修改CI3的会话读取逻辑。

方案3:模拟CI3登录请求

在CI4里用CURL模拟POST请求到CI3的登录接口,传递用户名和密码,让CI3自己生成会话,再跳转:

// CI4里的跳转逻辑替换为:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://localhost/CI3/login");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    'email' => $email,
    'password' => $this->request->getPost('password') // 注意CI3登录接口的参数名
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt'); // 保存cookie
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_exec($ch);
curl_close($ch);

// 跳转CI3仪表盘,携带cookie
return redirect()->to("http://localhost/CI3/dashboard");

注意:这种方法需要确保CI3的登录接口能接收POST参数,且要处理cookie的跨域问题(同域名下更可靠),安全性不如令牌方案。

原代码问题总结

直接跳转CI3时,CI3无法读取CI4的会话,因为两者的会话系统完全独立,必须通过中间验证机制(令牌、共享存储、模拟登录)来传递登录状态。

内容的提问来源于stack exchange,提问作者dev_programmer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 06:15:03