PHP7 入門研習

9-1 改寫 login()

一、改寫login()

  1. 原理說明:
    1. 先過濾並檢查變數(帳號)
    2. 拿帳號(email)到資料庫取抓取資料
    3. 若有,比對密碼是否正確,若正確,寫入session(包括姓名、群組、Email、編號)
    4. 若無,則登入失敗。
  2. 重新改寫login()變成資料庫版:
    //登入
    function login()
    {
        global $db;
        $email = $db->real_escape_string($_POST['email']);
        if (empty($email)) {
            throw new Exception("Eamil為必填!");
        }
        $email = filter_var($email, FILTER_VALIDATE_EMAIL);
        if (!$email) {
            throw new Exception("不合法的Email");
        }
    
        $pass = isset($_POST['pass']) ? $_POST['pass'] : '';
    
        $sql    = "SELECT * FROM `users` where `email`='{$email}'";
        $result = $db->query($sql);
        if (!$result) {
            throw new Exception($db->error);
        }
        $data = $result->fetch_assoc();
    
        if (password_verify($pass, $data['pass'])) {
            $_SESSION['group'] = $data['group'];
            $_SESSION['name']  = htmlspecialchars($data['name'], ENT_QUOTES);
            $_SESSION['uid']   = $data['uid'];
            $_SESSION['email'] = htmlspecialchars($data['email'], ENT_QUOTES);
        } else {
            throw new Exception("登入失敗!");
        }
    }
  3. 一樣先整理輸入的Email
  4. 利用email為唯一值的特性,讀取屬於該帳號的所有身家資料(且預計只會有一筆)。
  5. 利用 $result->fetch_assoc() 取出資料陣列,並存入$data中以便取用。其中,$data的陣列內容類似這樣:
    • $data['uid']=1;
    • $data['name']='tad';
    • $data['email']='tad@tn.edu.tw';
    • $data['pass']='xxxxx';
    • $data['group']='admin';
  6. 若是改用 $result->fetch_row() 取出資料陣列,$data的陣列內容則類似這樣(通常會搭配 list() 一起使用):
    • $data[0]=1;
    • $data[1]='tad';
    • $data[2]='tad@tn.edu.tw';
    • $data[3]='xxxxx';
    • $data[4]='admin';
  7. 利用 password_verify($pass, $data['pass']) 來檢查密碼是否正確
    1. 若正確,定義$_SESSION['group'] 及 $_SESSION['name'] 等值,表示登入。
    2. 若不正確,則丟出異常訊息。

二、修改登出

  1. 既然登入紀錄的東西已經不一樣,登出也要跟著改
    //登出
    function logout()
    {
        unset($_SESSION['group']);
        unset($_SESSION['name']);
        unset($_SESSION['uid']);
        unset($_SESSION['email']);
    }
    

三、練習:

  1. 請把要存入資料庫的值過濾、檢查部份寫成函數 clean_var(),並放到function.php中,以簡化程式。例如:
    $name = $db->real_escape_string($_POST['name']);
    if (empty($name)) {
        throw new Exception("姓名為必填!");
    }
    $email = $db->real_escape_string($_POST['email']);
    if (empty($email)) {
        throw new Exception("Eamil為必填!");
    }
    $email = filter_var($email, FILTER_VALIDATE_EMAIL);
    if (!$email) {
        throw new Exception("不合法的Email");
    }
    $pass = $db->real_escape_string($_POST['pass']);
    if (empty($pass)) {
        throw new Exception("密碼為必填!");
    }

    可簡化為

    $name  = clean_var('name', '姓名');
    $email = clean_var('email', 'Eamil', FILTER_VALIDATE_EMAIL);
    $pass  = clean_var('pass', '密碼');
  2. 參考答案:

    //檢查並傳回欲拿到資料使用的變數
    function clean_var($var = '', $title = '', $filter = '')
    {
        global $db;
        $clean_var = $db->real_escape_string($_REQUEST[$var]);
        if (empty($clean_var)) {
            throw new Exception("{$title}為必填!");
        }
        if ($filter) {
            $clean_var = filter_var($clean_var, $filter);
            if (!$clean_var) {
                throw new Exception("不合法的{$title}");
            }
        }
        return $clean_var;
    }