在使用php編程的時候,我有一個習慣,不太喜歡使用現成的庫文件,例如phplib或者其它類似的庫,在這個系統中,我也打算自己寫一個庫文件,它需要處理認證、確認email,更新帳號(密碼,email)等事情。
為了在保證該系統安全的同時,不會加重我現有數據庫的負擔。因此這個新的系統要依賴cookies。這確實是一個兩難的選擇,因為如果只是設置一個用戶名的cookie,是很不安全的,這行不通,但從數據庫的負擔考慮,我也不能加入一個簡單的無序碼而交由我的數據庫來進行驗證。
解決的方法是同時設置兩個cookie,一個是用戶名的cookie,一個是無序碼的cookie。這個無序碼實際上是由用戶名和一個超級密碼(只有程序設計者知道)組合通過md5()函數運算產生的。由于md5()是一個單向的無序碼,因此是不可以破解的。在用戶更改email時,我也可以用該email和超級密碼產生一個無序碼,以讓用戶確認修改。這實際上是一個公匙/私匙類的系統。不明白?不要緊,下面再慢慢說明。
有趣的是,這個系統的擴展能力是可以達到無窮的,因為該系統的主要工作是計算md5()函數的值,而且由web服務器完成,在負載增加時,可以加入其它的服務器來分擔負載,雖然認證系統不會拖跨一個數據庫,但是這樣做就讓最終的瓶頸只能出現在數據庫上。
<?php
function user_change_email ($password1,$new_email,$user_name) {
global $feedback,$hidden_hash_var;
if (validate_email($new_email)) {
$hash=md5($new_email.$hidden_hash_var);
file://改變數據庫中確認用的無序碼值,但不改變email
file://發出一個帶有新認證碼的確認email
$user_name=strtolower($user_name);
$password1=strtolower($password1);
$sql="update user set confirm_hash='$hash' where user_name='$user_name' and password='". md5($password1) ."'";
$result=db_query($sql);
if (!$result || db_affected_rows($result) < 1) {
$feedback .= ' error - incorrect user name or password ';
return false;
} else {
$feedback .= ' confirmation sent ';
user_send_confirm_email($new_email,$hash);
return true;
}
} else {
$feedback .= ' new email address appears invalid ';
return false;
}
}
function user_confirm($hash,$email) {
/*
用戶點擊認證email的相關連接時,連到一個確認的頁面,該頁面會調用這個函數,
*/
global $feedback,$hidden_hash_var;
file://verify that they didn't tamper with the email address
$new_hash=md5($email.$hidden_hash_var);
if ($new_hash && ($new_hash==$hash)) {
file://在數據庫中找出這個記錄
$sql="select * from user where confirm_hash='$hash'";
$result=db_query($sql);
if (!$result || db_numrows($result) < 1) {
$feedback .= ' error - hash not found ';
return false;
} else {
file://確認email,并且設置帳號為已經激活
$feedback .= ' user account updated - you are now logged in ';
user_set_tokens(db_result($result,0,'user_name'));
$sql="update user set email='$email',is_confirmed='1' where confirm_hash='$hash'";
$result=db_query($sql);
return true;
}
} else {
$feedback .= ' hash invalid - update failed ';
return false;
}
}
function user_send_confirm_email($email,$hash) {
/*
這個函數在首次注冊或者改變email地址時使用
*/
$message = "thank you for registering at company.com".
"/nsimply follow this link to confirm your registration: ".
"/n/nhttp://www.company.com/account/confirm.php?hash=$hash&email=". urlencode($email). "/n/nonce you confirm, you can use the services on phpbuilder.";
mail ($email,'registration confirmation',$message,'from:
[email protected]');
}
?>