實作網站阻止多重登入

by Ben
formula_math

前言

網紅啾啾鞋日前在他的 youtube 上放了個影片

說明他在 hahow 的線上課程在蝦皮上被盜賣的事情

其中影片的最後甚至實際測試了一波
發現 hahow 在網站上並無做多重登入的阻擋
也就是說 某A 和 某B 是可以同時登入同一個帳號來觀看線上課程
進而影響到內容創作者的權益

其實我覺得這種事是見人見智啦
就像是我買了一本書後 我也可以把這本書借給其他人讀
或是開個讀書會 大家一起讀

不過不管怎樣樣
多重登入就是不對
現在像是 Netflix、KKbox、PPT 等都有做多重登入的阻擋
就讓我們來看看怎麼阻擋多重登入吧

粗流

以下說明一下大致的流程

step 1


某 A 登入帳號時,建立 session
紀錄下 Session IDUser ID

step 2


某 B 登入時,檢查 session,查看其 User ID 是否已經登入
若有,則清除該 session,並新增 User ID 至 session 內
若無,則直接新增 User ID 至 session 內

step 3


加入即時檢查 user 是否仍在登入狀態的確認機制

程式碼 (ORM以 meedo 為例)

第一洞,建立 session table

欄位有: id、session_id、user_id

第二洞,每次登入時呼叫 checkPreviousLogin 確認是否有用同一帳號登入過,並回傳前一個登入者的 user_id

public static function checkPreviousLogin($sid, $currentUserID)
{
    $previousLoginUserID = mh()->get('session', [
        "userID"
    ], [
        "session_id[!]" =>$sid,
        "userID" => $currentUserID
    ]);

    return $previousLoginUserID;
}

第三洞,若有重複登入,清除該筆 session,並在本筆 session 內加入 errorMessage

public static function kickOut($previousUserID)
{
    mh()->delete('session', [
        'userID' => $previousUserID
    ]);

    return true;
}

f3()->set('SESSION.statusMsg', ["xxxxx重複登入xxxxxx,xxxxxxxxxxx"]);

第四洞,將 session_id 與對應的 user_id 寫入 session 表內

public static function updateUserID($sid, $currentUserID)
{
    mh()->update('session', [
        'userID' => $currentUserID,
        'stamp' => time()
    ], [
        'session_id' => $sid
    ]);

    return true;
}

第五洞,檢查在 session 內是否有 errorMessage

若有,則代表已重複登入,系統會顯示把前一個登入者踢掉的訊息,並把該 errorMessage 清掉

$msg = f3()->get('SESSION.statusMsg');
if (!empty($msg)) {
    $output['msg'] = $msg;
    f3()->clear('SESSION.statusMsg');
}

第六洞,每三分鐘檢查是否仍登入,若否,則 redirect 至首頁

checkDoubleLogin() {
    if (app.member.loginCheckTimer !== undefined) {
        return;
    }
    app.member.loginCheckTimer = window.setInterval(function() {
        let callback = function() {
            if (this.code === 0) {
                return;
            } else {
                app.modal.show({
                    src: 'message-modal',
                    message: {
                        content: '系統偵測帳戶已重複登入,將在三秒後強制登出',
                    }
                });
                setTimeout(function() {
                    window.location.href = `${window.location.origin}/home`;
                }, 3000);
            }
        };
        gee.yell("member/check", {}, callback, callback)
    }, 180000);
},

參考文件

You may also like

Leave a Comment