一個(gè)完整、安全的用戶登錄系統(tǒng)_PHP教程
推薦:面向搜索引擎的URL優(yōu)化我在寫晉遠(yuǎn)信息網(wǎng)(www.geofuture.net)時(shí)沒有考慮到URL如何面向搜索引擎優(yōu)化,完成了以后才開始優(yōu)化的。這時(shí)要考慮一方面要靜態(tài)的URL,一方面要盡量保持原有的程序不變以便于以后維護(hù),所以就采
在使用PHP編程的時(shí)候,我有一個(gè)習(xí)慣,不太喜歡使用現(xiàn)成的庫文件,例如PHPLib或者其它類似的庫,在這個(gè)系統(tǒng)中,我也打算自己寫一個(gè)庫文件,它需要處理認(rèn)證、確認(rèn)email,更新帳號(密碼,email)等事情。
為了在保證該系統(tǒng)安全的同時(shí),不會加重我現(xiàn)有數(shù)據(jù)庫的負(fù)擔(dān)。因此這個(gè)新的系統(tǒng)要依賴cookies。這確實(shí)是一個(gè)兩難的選擇,因?yàn)槿绻皇窃O(shè)置一個(gè)用戶名的cookie,是很不安全的,這行不通,但從數(shù)據(jù)庫的負(fù)擔(dān)考慮,我也不能加入一個(gè)簡單的無序碼而交由我的數(shù)據(jù)庫來進(jìn)行驗(yàn)證。
解決的方法是同時(shí)設(shè)置兩個(gè)cookie,一個(gè)是用戶名的cookie,一個(gè)是無序碼的cookie。這個(gè)無序碼實(shí)際上是由用戶名和一個(gè)超級密碼(只有程序設(shè)計(jì)者知道)組合通過md5()函數(shù)運(yùn)算產(chǎn)生的。由于md5()是一個(gè)單向的無序碼,因此是不可以破解的。在用戶更改email時(shí),我也可以用該email和超級密碼產(chǎn)生一個(gè)無序碼,以讓用戶確認(rèn)修改。這實(shí)際上是一個(gè)公匙/私匙類的系統(tǒng)。不明白?不要緊,下面再慢慢說明。
有趣的是,這個(gè)系統(tǒng)的擴(kuò)展能力是可以達(dá)到無窮的,因?yàn)樵撓到y(tǒng)的主要工作是計(jì)算md5()函數(shù)的值,而且由web服務(wù)器完成,在負(fù)載增加時(shí),可以加入其它的服務(wù)器來分擔(dān)負(fù)載,雖然認(rèn)證系統(tǒng)不會拖跨一個(gè)數(shù)據(jù)庫,但是這樣做就讓最終的瓶頸只能出現(xiàn)在數(shù)據(jù)庫上。
以下是該庫中的兩個(gè)函數(shù)--記號產(chǎn)生和記號認(rèn)證函數(shù)。
以下為引用的內(nèi)容: 。?php $hidden_hash_var='your_secret_password_here'; $LOGGED_IN=false; function user_isloggedin() { file://如果是的話,返回該變量 if ( isset($LOGGED_IN) ) { return $LOGGED_IN; } file://are both cookies present? if ($user_name && $id_hash) { /* |
由cookies中得來的用戶名和系統(tǒng)超級密碼產(chǎn)生一個(gè)認(rèn)證用的無序碼如果該無序碼與cookie中的無序碼一樣,則cookies中的變量是可信的,用戶已經(jīng)登錄。
以下為引用的內(nèi)容: */ $hash=md5($user_name.$hidden_hash_var); if ($hash == $id_hash) { file://無序碼符合,設(shè)置一個(gè)全局變量,這樣我們在再次調(diào)用該函數(shù)的時(shí)候, file://就無需再次進(jìn)行md5()運(yùn)算 $LOGGED_IN=true; return true; } else { file://兩個(gè)無序碼不符合,沒有登錄 $LOGGED_IN=false; return false; } } else { $LOGGED_IN=false; return false; } } function user_set_tokens($user_name_in) { /* |
一旦用戶名和密碼通過驗(yàn)證,就調(diào)用這個(gè)函數(shù)
以下為引用的內(nèi)容: */ global $hidden_hash_var,$user_name,$id_hash; if (!$user_name_in) { $feedback .= ' ERROR - User Name Missing When Setting Tokens '; return false; } $user_name=strtolower($user_name_in); file://使用用戶名和超級密碼創(chuàng)建一個(gè)無序碼,作判斷是否已經(jīng)登錄用 $id_hash= md5($user_name.$hidden_hash_var); file://設(shè)置cookies的有效期為一個(gè)月,可設(shè)置為任何的值 setcookie('user_name',$user_name,(time() 2592000),'/','',0); setcookie('id_hash',$id_hash,(time() 2592000),'/','',0); } ?> |
再來看另一段有趣的代碼,用戶怎樣才能安全地改變他們的email地址呢?他們可以在任何時(shí)候改變email地址,但是要進(jìn)行確認(rèn)。
以下為引用的內(nèi)容: 。?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://改變數(shù)據(jù)庫中確認(rèn)用的無序碼值,但不改變email file://發(fā)出一個(gè)帶有新認(rèn)證碼的確認(rèn)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) { /* |
用戶點(diǎn)擊認(rèn)證email的相關(guān)連接時(shí),連到一個(gè)確認(rèn)的頁面,該頁面會調(diào)用這個(gè)函數(shù)
以下為引用的內(nèi)容: */ 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://在數(shù)據(jù)庫中找出這個(gè)記錄 $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://確認(rèn)email,并且設(shè)置帳號為已經(jīng)激活 $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) { /* |
這個(gè)函數(shù)在首次注冊或者改變email地址時(shí)使用
以下為引用的內(nèi)容: */ $message = "Thank You For Registering at Company.com". "\nSimply follow this link to confirm your registration: ". } ?> |
評論:或許我們在用戶認(rèn)證方面不是采用這種方法,而是采用session等方式,不過這篇文章在如何進(jìn)行加密和確認(rèn)方面,還是對我們有所啟發(fā)的。
分享:PHP空白頁面常見原因及解決方法編寫PHP,難免會出現(xiàn)錯(cuò)誤。其實(shí)出現(xiàn)錯(cuò)誤也不難解決,最難解決的是出現(xiàn)空白頁面。大家想想看,若編寫PHP出現(xiàn)錯(cuò)誤,可以根據(jù)錯(cuò)誤的提示來改正,倘若PHP什么也不給你顯示,那豈不是讓編寫者困撓不
- PHPNOW安裝Memcached擴(kuò)展方法詳解
- php記錄頁面代碼執(zhí)行時(shí)間
- PHP中獎(jiǎng)概率的抽獎(jiǎng)算法程序代碼
- apache設(shè)置靜態(tài)文件緩存方法介紹
- php對圖像的各種處理函數(shù)代碼小結(jié)
- PHP 關(guān)于訪問控制的和運(yùn)算符優(yōu)先級介紹
- 關(guān)于PHP語言構(gòu)造器介紹
- php/js獲取客戶端mac地址的實(shí)現(xiàn)代碼
- php5.5新數(shù)組函數(shù)array_column使用
- PHP preg_match的匹配多國語言的技巧
- php 中序列化和json使用介紹
- php采集文章中的圖片獲取替換到本地
PHP教程Rss訂閱編程教程搜索
PHP教程推薦
- PHP技術(shù)進(jìn)階 用PHP處理多個(gè)同名復(fù)選框
- 解析用PHP讀寫音頻文件信息的詳解(支持WMA和MP3)
- 如何在PHP中實(shí)現(xiàn)文件的上傳功能
- php 站點(diǎn)使用XML文件做配置類
- PHP最常用的2種設(shè)計(jì)模式:工廠模式和單例模式
- 詳解PHP的Jmai組件及發(fā)送郵件實(shí)例
- 關(guān)于php循環(huán)跳出的問題
- 用PHP操縱Oracle的LOB類型的數(shù)據(jù)
- 談從魔獸看PHP設(shè)計(jì)模式
- 新手入門:初學(xué)動(dòng)態(tài)網(wǎng)頁P(yáng)HP的18個(gè)例子
- 相關(guān)鏈接:
- 教程說明:
PHP教程-一個(gè)完整、安全的用戶登錄系統(tǒng)。