9-1
改寫 login()
一、改寫login()
- 原理說明:
- 先過濾並檢查變數(帳號)
- 拿帳號(email)到資料庫取抓取資料
- 若有,比對密碼是否正確,若正確,寫入session(包括姓名、群組、Email、編號)
- 若無,則登入失敗。
- 重新改寫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("登入失敗!");
}
}
- 一樣先整理輸入的Email
- 利用email為唯一值的特性,讀取屬於該帳號的所有身家資料(且預計只會有一筆)。
- 利用 $result->fetch_assoc() 取出資料陣列,並存入$data中以便取用。其中,$data的陣列內容類似這樣:
- $data['uid']=1;
- $data['name']='tad';
- $data['email']='tad@tn.edu.tw';
- $data['pass']='xxxxx';
- $data['group']='admin';
- 若是改用 $result->fetch_row() 取出資料陣列,$data的陣列內容則類似這樣(通常會搭配 list() 一起使用):
- $data[0]=1;
- $data[1]='tad';
- $data[2]='tad@tn.edu.tw';
- $data[3]='xxxxx';
- $data[4]='admin';
- 利用 password_verify($pass, $data['pass']) 來檢查密碼是否正確
- 若正確,定義$_SESSION['group'] 及 $_SESSION['name'] 等值,表示登入。
- 若不正確,則丟出異常訊息。
二、修改登出
- 既然登入紀錄的東西已經不一樣,登出也要跟著改
//登出
function logout()
{
unset($_SESSION['group']);
unset($_SESSION['name']);
unset($_SESSION['uid']);
unset($_SESSION['email']);
}
三、練習:
- 請把要存入資料庫的值過濾、檢查部份寫成函數 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', '密碼');
-
參考答案:
//檢查並傳回欲拿到資料使用的變數
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;
}