Rumah  >  Artikel  >  rangka kerja php  >  Perkongsian pada pit: Proses penyepaduan Laravel phpCAS

Perkongsian pada pit: Proses penyepaduan Laravel phpCAS

藏色散人
藏色散人ke hadapan
2021-09-19 16:53:491816semak imbas

Lajur tutorial Laravel berikut akan berkongsi dengan anda perangkap Laravel yang menyepadukan phpCAS, saya harap ia akan membantu rakan-rakan yang memerlukannya.

Perangkap phpCAS bersepadu Laravel

CAS kini merupakan protokol log masuk tunggal yang popular Setakat ini , Setakat ini, gaya pengekodannya kekal dalam era PEAR, tanpa menggunakan ruang nama pun. Nasib baik, phpCAS menyokong pengenalan komposer, dan saya telah melakukan beberapa pengenalan projek Laravel tanpa sebarang masalah, dalam dua hari yang lalu, projek perlu diubah daripada penggunaan mesin tunggal kepada penggunaan berbilang mesin langkah pada beberapa perangkap di sini saya akan merakam mereka di sini.

Callback Pit

Apabila melompat ke Pelayan CAS untuk pengesahan, kami mendapati port 8080 telah ditambahkan pada alamat panggil balik masuk. Oleh kerana ia adalah penggunaan berbilang mesin, permintaan akses akan mula-mula melalui pengimbang beban (Alibaba Cloud SLB) dan kemudian mencapai pelayan web, dan 8080 ini ialah port mendengar pelayan web.

Jadi saya mengesan logik phpCAS untuk menjana alamat panggil balik dan menemui sekeping kod ini:

if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
    $server_port = $_SERVER['SERVER_PORT'];
} else {
    $ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']);
    $server_port = $ports[0];
}

SLB Alibaba Cloud tidak menghantar pengepala http ini ke pelayan hujung belakang X-FORWARDED-PORT . Oleh itu, phpCAS akan mendapat $_SERVER['SERVER_PORT'], iaitu port 8080 nginx.

Nasib baik, phpCAS menyediakan fungsi setFixedServiceURL, yang membolehkan kami menetapkan alamat panggilan balik secara manual:

phpCAS::setFixedServiceURL($request->url());

Alamat panggil balik adalah perkara biasa sekarang, tetapi ia kembali daripada Pelayan CAS ke pelanggan saya diberitahu bahawa tiket itu tidak sah.

Terus menyemak log dan kod, saya mendapati bahawa saya cuai di sini Apabila Pelayan CAS kembali kepada pelanggan, url halaman adalah http://client/login?ticket=xxxxx, dan pelanggan perlu membawanya bersamanya. apabila menggunakan tiket untuk bertukar-tukar maklumat pengguna dengan pelayan Alamat panggilan balik (perkhidmatan) semasa memohon tiket, pelayan akan mengesahkan sama ada tiket dan perkhidmatan adalah konsisten, dan perkhidmatan semasa memohon tiket hendaklah http://client/login, jadi. kita perlu mengalih keluar parameter tiket dalam url.

phpCAS::setFixedServiceURL($this->getUrlWithoutTicket($request));

getUrlWithoutTicket Fungsinya adalah seperti berikut:

private function getUrlWithoutTicket(Request $request)
{
    $query = parse_query($request->getQueryString());
    unset($query['ticket']);
    $question = $request->getBaseUrl().$request->getPathInfo() == '/' ? '/?' : '?';

    return $query ? $request->url().$question.http_build_query($query) : $request->url();
}

Session Pit

Ini ialah gabungan pit phpCAS Laravel, yang membuatkan anda hilang sabar .

Kaedah storan lalai PHP untuk sesi ialah fail, jadi perkara yang sangat penting apabila menukar satu mesin kepada berbilang mesin adalah untuk mengendalikan perkongsian sesi. Penyelesaiannya juga sangat mudah, iaitu menukar kaedah penyimpanan Sesi daripada fail kepada redis/memecache/pangkalan data, dsb.

Laravel menyediakan pemacu ini secara lalai, jadi saya teruja menukar fail .env dan menukar SESSION_DRIVER kepada redis. Saya mencubanya dalam talian dan mendapati ia tidak berfungsi Perubahan yang dibuat oleh phpCAS kepada pembolehubah $_SESSION tidak ditulis kepada redis.

Jadi saya mengikuti pelaksanaan Sesi Laravel dan mendapati bahawa ia bukanlah penggunaan session_set_save_handler yang dibayangkan untuk mendaftar logik membaca dan menulis Sesi Dengan kata lain, Sesi Laravel sebenarnya tidak mengubah suai pembacaan dan penulisan PHP $_SESSION Logik, kendalikan terus $_SESSION atau ikut tingkah laku lalai (baca dan tulis fail tempatan).

Nah, mujurlah, beberapa Laravel SessionDriver telah melaksanakan antara muka SessionHandlerInterface, dan kami boleh memanggilnya sendiri session_set_save_handler:

session_set_save_handler(app(StartSession::class)->getSession($request)->getHandler());

Saya tidak pernah menjangka akan melaporkan ralat!

session_write_close(): Session callback expects true/false return value

Saya mengesan kod Laravel dan mendapati bahawa kaedah IlluminateSessionCacheBasedSessionHandler kelas induk pemandu redis write mengembalikan void. Jadi saya menyerahkan PR untuk membetulkannya, tetapi saya tidak menjangkakan ia akan ditolak. t mencari isu khusus.

Nah, memcache dan redis kedua-duanya mewarisi kelas induk ini, jadi saya akan cuba pangkalan data sebaliknya.

Kali ini session_write_close tiada ralat dilaporkan, tetapi masih terdapat masalah dengan log masuk CAS, dan ia terus melompat antara pelayan CAS dan url panggil balik. Jadi saya mengejar semua log dan kod dan mendapati bahawa kaedah IlluminateSessionDatabaseSessionHandler kelas pemacu pangkalan data destroy tidak menandakan atribut $this->exists sebagai false selepas memusnahkan Sesi, dan phpCAS mempunyai logik renameSession

$old_session = $_SESSION;
session_destroy();
$session_id = preg_replace('/[^a-zA-Z0-9\-]/', '', $ticket);
session_id($session_id);
session_start();
$_SESSION = $old_session;

Akibatnya ialah $_SESSION = $old_session; operasi sql yang sepadan pada jadual sesi melaksanakan kemas kini dan bukannya memasukkan, iaitu, data sesi tidak boleh ditulis ke jadual sesi!

Sebenarnya tiada cara lain selain menulis Pembungkus Sesi untuk mengendalikannya.

Daripada dua situasi di atas, pemacu redis lebih mudah dikendalikan, selagi ia boleh kembali benar apabila memanggil kaedah tulis. Jadi kodnya adalah seperti berikut

namespace App\Services;

use SessionHandlerInterface;

class MySession implements SessionHandlerInterface
{
    /**
     * @var SessionHandlerInterface
     */
    protected $realHdl;

    /**
     * Session constructor.
     * @param SessionHandlerInterface $realHdl
     */
    public function __construct(SessionHandlerInterface $realHdl)
    {
        $this->realHdl = $realHdl;
    }

    public function close()
    {
        return $this->realHdl->close();
    }

    public function destroy($session_id)
    {
        return $this->realHdl->destroy($session_id);
    }

    public function gc($maxlifetime)
    {
        return $this->realHdl->gc($maxlifetime);
    }

    public function open($save_path, $name)
    {
        return $this->realHdl->open($save_path, $name);
    }

    public function read($session_id)
    {
        return $this->realHdl->read($session_id) ?: '';
    }

    public function write($session_id, $session_data)
    {
        $this->realHdl->write($session_id, $session_data);

        return true; // 这里
    }
}

dan kemudian memanggil session_set_save_handler menjadi

session_set_save_handler(new MySession(app(StartSession::class)->getSession($request)->getHandler()));

Selesai!

Atas ialah kandungan terperinci Perkongsian pada pit: Proses penyepaduan Laravel phpCAS. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:segmentfault.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam