โ† Semua pembelajaran / Astro Nol โ†’ Portal Berita
Fase 5 ยท Membership, Auth & Paywall

Sesi bersama selama CI3 dan Astro hidup berdampingan

Selama Fase 9, sebagian halaman masih dilayani CI3 dan sebagian sudah Astro. Kalau sesi keduanya tidak nyambung, pembaca akan ter-logout setiap kali menyeberang.

Sumber asli owasp.org Artikel Rangkuman ~9 menit baca

Intisari

  • Isi ci_sessions.data adalah format serialisasi PHP, bukan JSON. Node tidak bisa membacanya tanpa parser khusus.
  • Tiga jalan: parser PHP di Node, tabel sesi kedua yang dibagi, atau memaksa login ulang sekali.
  • Yang direkomendasikan: tabel sesi baru yang dibaca CI3 dan Astro. CI3 disunting sedikit, sekali.
  • Nama cookie harus berbeda selama transisi supaya keduanya tidak saling menimpa.
  • Apa pun jalannya, siapkan rencana untuk sesi yang ditinggalkan โ€” jangan biarkan menumpuk selamanya.

Kenapa ini masalah

Isi kolom ci_sessions.data:

__ci_last_regenerate|i:1756281600;member_id|i:4471;nama|s:11:"Budi Santos";

Ini format serialize() PHP. Node tidak punya padanan bawaannya.

Ditambah komplikasi: kalau CI3-mu memakai $config['sess_encrypt_cookie'] atau menyimpan sesi di berkas alih-alih database, isinya bahkan tidak ada di MySQL sama sekali.

Tiga jalan keluar

Parser PHP di NodeTabel sesi bersamaPaksa login ulang
Perubahan di CI3Tidak adaSedikit, sekaliTidak ada
Perubahan di AstroParser + penulisan format PHPBaca tabel baruTidak ada
Pembaca ter-logoutTidakTidakYa, semuanya
KerapuhanTinggi โ€” dua sistem menulis format yang samaRendahNol
Cocok kalauHampir tidak pernahMigrasi bertahapPeluncuran sekali jalan

Jalur pertama terlihat paling elegan dan justru paling berbahaya. Membaca serialisasi PHP bisa dilakukan; menulisnya dari Node dengan cara yang tidak pernah membingungkan CI3 jauh lebih sulit. Dan bug di sini bukan bug tampilan โ€” ia bug sesi, yang berarti pembaca bisa mendapat sesi orang lain. Jangan tempuh jalur ini kecuali tidak ada pilihan.

Jalur yang direkomendasikan: tabel sesi bersama

Buat tabel sesi baru (bentuknya di materi sebelumnya), lalu ajari CI3 membacanya. Perubahan di CI3 kecil dan dilakukan sekali.

// application/libraries/Sesi_bersama.php
class Sesi_bersama {

    private $CI;
    private $member = null;

    public function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->load->database();
    }

    public function member()
    {
        if ($this->member !== null) return $this->member;

        $id = $this->CI->input->cookie('__Host-sesi', TRUE);

        if (!$id || strlen($id) !== 43) return $this->member = FALSE;

        $row = $this->CI->db
            ->select('m.id, m.nama, m.email, m.peran')
            ->from('sesi s')
            ->join('member m', 'm.id = s.member_id')
            ->where('s.id', $id)
            ->where('s.kedaluwarsa >', date('Y-m-d H:i:s'))
            ->where('m.status', 'aktif')
            ->get()->row();

        return $this->member = ($row ?: FALSE);
    }
}

Lalu ganti $this->session->userdata('member_id') di CI3 dengan $this->sesi_bersama->member()->id. Cari-ganti sekali, dan setelah itu kedua aplikasi membaca sumber kebenaran yang sama.

Arah penulisannya penting: Astro yang menulis, CI3 yang membaca. Login dan logout dipindahkan ke Astro sejak awal โ€” itu halaman yang sederhana dan tidak banyak, jadi layak jadi yang pertama dimigrasikan. CI3 tidak perlu tahu cara membuat sesi sama sekali, cuma cara membacanya. Satu penulis, banyak pembaca, adalah rancangan yang jauh lebih sulit dirusak.

Nama cookie harus berbeda

CI3   : ci_session          (biarkan, jangan disentuh)
Astro : __Host-sesi         (baru)

Kalau keduanya memakai nama yang sama, siapa pun yang menulis terakhir menang, dan pembaca akan ter-logout secara acak tergantung halaman mana yang terakhir dibuka. Biarkan ci_session tetap ada dan diabaikan; ia akan mati sendiri saat CI3 dimatikan.

Masa transisi: memindahkan sesi yang sudah ada

Saat peluncuran, member yang sedang login punya ci_session tapi belum punya __Host-sesi. Dua pilihan:

// Di CI3, saat member membuka halaman apa pun:
// kalau ia punya sesi CI3 tapi belum punya sesi baru, buatkan.
$member_id = $this->session->userdata('member_id');

if ($member_id && !$this->input->cookie('__Host-sesi')) {
    $id = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');

    $this->db->insert('sesi', [
        'id'           => $id,
        'member_id'    => $member_id,
        'dibuat_pada'  => date('Y-m-d H:i:s'),
        'dipakai_pada' => date('Y-m-d H:i:s'),
        'kedaluwarsa'  => date('Y-m-d H:i:s', time() + 2592000),
    ]);

    setcookie('__Host-sesi', $id, [
        'expires'  => time() + 2592000,
        'path'     => '/',
        'secure'   => TRUE,
        'httponly' => TRUE,
        'samesite' => 'Lax',
    ]);
}

random_bytes(), bukan rand() atau uniqid(). Ini pembuatan ID sesi โ€” satu-satunya sumber acak yang boleh dipakai adalah yang kriptografis.

Jalankan jembatan ini selama beberapa minggu, lalu hapus. Setelah itu, member yang belum menyeberang tinggal login lagi seperti biasa.

Kalau kamu memilih memaksa login ulang

Ini pilihan yang sah, dan untuk portal dengan basis member kecil sering merupakan yang paling waras. Syaratnya: umumkan sebelumnya, dan pastikan alur "lupa password" bekerja sempurna di hari peluncuran โ€” karena sebagian orang akan lupa.

Yang tidak boleh: memaksa login ulang dan ternyata hash password-nya juga tidak bisa diverifikasi. Kombinasi itu berarti setiap member harus reset password lewat email di hari yang sama โ€” dan penyedia emailmu akan menganggap lonjakan itu sebagai spam lalu memblokirnya. Selesaikan materi password lebih dulu.

Setelah CI3 dimatikan

-- Pastikan tidak ada lagi yang menulis ke sana
SELECT MAX(FROM_UNIXTIME(timestamp)) FROM ci_sessions;

-- Kalau sudah lewat beberapa minggu tanpa aktivitas:
DROP TABLE ci_sessions;

Latihan: periksa konfigurasi sesi CI3-mu sekarang โ€” sess_driver, sess_save_path, dan apakah sess_encrypt_cookie aktif. Kalau drivernya files, catat itu: berarti sesi tidak ada di database sama sekali dan jalur "parser PHP" otomatis gugur. Lalu tulis library Sesi_bersama di CI3-mu dan buktikan ia bisa membaca sesi yang dibuat Astro.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.