PHP 取得使用者 IP 並運用 Session 建立登入次數限制機制

2019/06/30 3,389 2 網站技術 , 資訊安全 , PHP

自己特別在網路上找了相關的資料,發現真的很少人直接寫這樣的主題還提供原始碼,因為資安這種東西敘述起來不算容易,且原始碼給出來後又容易給別人抓到邏輯漏洞,但其實擁有這種知識的人應該更有道德,不運用自己的知識去破壞他人的財產,很多東西就是防君子不防小人,就跟你家的大門鎖一樣的道理,若真的有人使用暴力,在強大的鎖都不會有太大的作用,但依然能起點效果,例如拖歹徒的時間與耐心,所以基本上還是要做這樣的防護機制,不然大家都不鎖門就好了呀!😜 廢話說到這,本文當然不給完整原始碼(資安問題),但會給很完整的概念與片段原始碼提供參考(盡量由上至下解說),以下的原始碼都是寫在同一個 .php 檔案中,我們馬上開始!😎

⚠ 關於 Session 的啟動

沒錯!這次要運用到 Session 來存放登入狀態,所以程式開頭一定要先啟動 Session 唷!原始碼:

session_start();

⌨ PHP 取得使用者 IP

首先我想最基本的就是先用 PHP 取得使用者 IP,不過說真的這只是拿來做判斷是不是同個人在重複登入,如果有人去竄改 IP 可就沒輒了!不過再次強調!這篇文章介紹的技巧都是初等的,只防君子不防小人!原始碼:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $userip = $_SERVER['HTTP_CLIENT_IP'];
} else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $userip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $userip = $_SERVER['REMOTE_ADDR'];
}

用 $_SERVER 取得使用者 IP 並存入變數 $userip 中,有三種不同的取得方式,依照可信程度排列(越上面越可信),方便我們做 IP 記錄。

※ 2019/08/18 更新:上方為原始練習的版本,正式狀態建議使用 REMOTE_ADDR 取得真實 IP,其他(例如:HTTP_CLIENT_IP)皆可以透過修改 header 來竄改 IP,因此上方的原始碼建議修正成以下的版本:

$userip = $_SERVER['REMOTE_ADDR'];

🤔 關於限制值與使用者 IP 的初始寫入設定

限制值我們要用 Session 存入,變數我先這樣設定(這邊當然還不用打入程式中):

$_SESSION["login_limit"]

使用者 IP 也是要用 Session 存入,變數我先這樣設定(這邊也當然還不用打入程式中):

$_SESSION["userip"]

為了不要干擾已經存在的 Session 限制值(因為限制值等於 0 代表遭到限制登入),首先要先檢查 Session 限制值是否存在,如果不存在且剛剛取得的使用者 IP 與前次 Session 存入的 IP(或者空值)不同,就可以直接設定以下原始碼:

if (!isset($_SESSION["login_limit"])) { // 如果尚未寫入限制值
    if ($userip != $_SESSION["userip"]) { // 確認現在的 IP 跟之前可能存過的 IP 不同
        $_SESSION["login_limit"] = 10; // 限制同個 IP 只能嘗試十次登入
    }
}

接下來判斷使用者是否是首次使用,所以先判斷 Session 使用者 IP 是否存在,不存在才將剛剛取得的使用者 IP 存入 Session 的使用者 IP 中,原始碼:

if (!isset($_SESSION["userip"])) { // 如果尚未寫入使用者 IP
    $_SESSION["userip"] = $userip; // 將使用者 IP 存入 Session
}

😎 重點區段:判斷 Session 限制值,以確定要繼續執行還是封鎖使用者登入

邏輯上,Session 限制值只要小於等於 0 就視為使用者已經登入超過限制次數,直接封鎖啦!此段原始碼如下:

if ($_SESSION["login_limit"] <= 0) {

echo "您的登入次數超過限制,已被限制登入!";

} else {

    // 尚未超過登入限制次數要執行的原始碼(這邊是登入主程式)

}

🤯 登入主程式內建立登入次數限制機制

感覺這邊有點燒腦,不過說起來非常簡單,就是帳密與資料庫對比後會有成功與失敗兩個區塊,成功區塊將 Session 限制值直接設定回預設值就完成了!原始碼:

$_SESSION["login_limit"] = 10; // 登入成功將次數設回限制值

失敗的區塊就稍微複雜些了!基本上判斷現在使用者 IP 與 Session 內的 IP 一樣就將 Session 限制次數 -1,若不一樣就將次數設回限制值,還要指定使用者 IP 存入 Session IP 變數中,不一樣的狀況大概是 IP 有變更,不過我覺得不做「不一樣」的部分好像也能跑。原始碼:

if ($userip == $_SESSION["userip"]) { // IP 一樣就將次數-1
                        $_SESSION["login_limit"]--;
                    } else { // IP 不一樣就將次數設回限制值
                        $_SESSION["userip"] = $userip;
                        $_SESSION["login_limit"] = 10;
}

當然失敗區塊可以傳回「您還有?次的登入機會」這樣的訊息唷!範例原始碼:

echo "您還有" . $_SESSION["login_limit"] . "次的登入機會";

唯一覺得怪的是被封鎖前最後顯示的是「您還有0次的登入機會」,不過這用 if 判斷句可以解決,但我覺得這樣顯示也沒差啦!的確是只剩 0 次機會 😂。

💬 更多雜談

沒錯!您已經看完所有原始碼,基本上這樣做就可以有一個很基本的登入次數限制機制,不過我真的建議將每次的登入記錄都存入網站的資料庫中,適時用人工的方式檢視惡意的登入,這樣就可以確保網站更加安全囉!這邊沒有談到存入資料庫的方式,我自己在系統中就有這樣設計,IP 的取得也是為了存入資料庫,所以您可以試試看這樣的作法,會比較保險!不過相信要看懂這篇文章您應該也要會存東西到資料庫中了!所以就不多說詳細作法與給原始碼啦!🤣 寫程式真的燒腦,我要去吃東西了!😋


▲ 登入次數限制示意圖。

贊助廣告 ‧ Sponsor advertisements

留言區 / Comments

萌芽論壇