一個(gè)完整、安全的用戶登錄系統(tǒng)_PHP教程

      編輯Tag賺U幣
      教程Tag:暫無Tag,歡迎添加,賺取U幣!

      推薦:面向搜索引擎的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;
         unset($LOGGED_IN);

         function user_isloggedin() {
          global $user_name,$id_hash,$hidden_hash_var,$LOGGED_IN;
          file://已經(jīng)進(jìn)行無序碼的檢測了嗎

          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: ".
             "\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: noreply@company.com');

            }

          ?>

      評論:或許我們在用戶認(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什么也不給你顯示,那豈不是讓編寫者困撓不

      來源:模板無憂//所屬分類:PHP教程/更新時(shí)間:2008-08-22
      相關(guān)PHP教程