ข้ามไปยังเนื้อหาหลัก
ProgrammerThailand

Yii Framework 2 (Yii2)

กำหนดให้ Login ใช้งาน Session เดียวใน Yii Framework 2

ปัญหานี้เกิดขึ้นเมื่อสมาชิก (user) เดียว แต่สามารถ login เข้าระบบได้จากหลายๆ เครื่อง หลายๆ browser ทำให้ไม่สามารถควบคุมการใช้งานได้ เช่น user A เข้าเรียนหลักสูตร aaa ได้ จากนั้น user A เอา username และ password ไปแจกเพื่อนๆ 9 คน ซึ่งแต่ละคนก็จะสามารถ login เข้ามาเรียนหลักสูตร aaa ได้ ทำให้เกิดปัญหาและความเสียหายต่อผู้ให้บริการ

แนวทางการแก้ไขคือ เมื่อ user A login ให้ทำการลบ session อื่นๆ ที่กำลัง login ออกทั้งหมด และการแก้ไขในปัญหานี้สำหรับ Yii Framework จะใช้ Session ที่เก็บใน Database เป็นตัวจัดการนั่นเอง เริ่มกันเลย

สร้าง migration กันก่อนนะ

cmd

yii migrate/create create_session_table

จากนั้นแก้ไขไฟล์ที่สร้างขึ้นใน console/migrations/xxxx_xxxx_create_session_table.php ดังนี้

<?php

use yii\db\Migration;

/**
 * Handles the creation of table `session`.
 */
class m170927_114732_create_session_table extends Migration
{
    /**
     * @inheritdoc
     */
    public function up()
    {
        $this->createTable('session', [
            'id' => $this->char(40)->notNull(),
            'expire' => $this->integer(),
            'data' => $this->binary(),
            'user_id' => $this->integer()
        ]);

        $this->addPrimaryKey('session_pk', 'session', 'id');
    }

    /**
     * @inheritdoc
     */
    public function down()
    {
        $this->dropTable('session');
    }
}

cmd ประมวลผล

yii migrate

จากนั้นทำการ generate model ด้วย gii generator เก็บไว้ใน common\models\Session.php

 

จากนั้นแก้ไขการตั้งค่า session ในส่วน components เพื่อให้เรียกใช้ session ใน database โดยแก้ไข frontend/config/main.php เพิ่มเติมส่วน session ใน components

//....
    'components' => [

        //...
        'session' => [
            'name' => 'EOFFICE',
            'class' => 'yii\web\DbSession',
            'sessionTable' => 'session',//ชื่อตารางเก็บ session
            'writeCallback' => function($session){
                
                return [
                    'user_id' => Yii::$app->user->id//กำหนด user_id
                ];
            }
        ],
        //...

    ]

จากนั้นปรับแต่ง actionLogin() ใน frontend/controllers/SiteController.php เพื่อให้ลบ Session จากเครื่อง/browser อื่นๆ ดังนี้

public function actionLogin()
    {
        //$this->layout = 'login';
        if (!Yii::$app->user->isGuest) {
            return $this->goHome();
        }

        $model = new LoginForm();
        if ($model->load(Yii::$app->request->post()) && $model->login()) {
            Session::deleteAll(['and', 'user_id = '.Yii::$app->user->getId(), "id != '".Yii::$app->session->id."'"]); //ส่วนที่เพิ่มเติม อย่าลืม use common\models\Session; ก่อนล่ะ
            return $this->goBack();
        } else {
            return $this->render('login', [
                'model' => $model,
            ]);
        }
    }

ทดสอบโดยการ login จากหลายๆ browser จากนั้น ลอง refresh แต่ละ browser จะเหลือ login concurrent เพียงที่ login ใน browser ตัวล่าสุดนั่นเอง

หมายเหตุ ต้องไม่เลือก remember me นะครับ

นี่เป็นเพียงวิธีการหนึ่งเท่านั้น หากเพื่อนๆ มีทางอื่นๆ ที่ดีกว่าช่วยแจ้งด้วยนะครับ

 

ติดปัญหาตอนทำตาม? ถามในชุมชน

ความคิดเห็น (0)

ยังไม่มีความคิดเห็น — เริ่มคุยเป็นคนแรก ถามสิ่งที่สงสัย หรือแชร์ประสบการณ์ของคุณ