设为首页 收藏本站
查看: 531|回复: 0

[经验分享] PHP开发一个完整、安全的用户登录系统

[复制链接]

尚未签到

发表于 2017-4-10 06:40:52 | 显示全部楼层 |阅读模式
  在使用PHP编程的时候,我有一个习惯,不太喜欢使用现成的库文件,例如PHPLib或者其它类似的库,在这个系统中,我也打算自己写一个库文件,它需要处理认证、确认email,更新帐号(密码,email)等事情。
  <?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".
        "
Simply follow this link to confirm your registration: ".
       "
http://www.company.com/account/confirm.php?hash=$hash&email=". urlencode($email). "
Once you confirm, you can use the services on PHPBuilder.";
mail ($email,'Registration Confirmation',$message,'From: noreply@company.com');
      }
     ?>
  评论:或许我们在用户认证方面不是采用这种方法,而是采用session等方式,不过这篇文章在如何进行加密和确认方面,还是对我们有所启发的。
  为了在保证该系统安全的同时,不会加重我现有数据库的负担。因此这个新的系统要依赖cookies。这确实是一个两难的选择,因为如果只是设置一个用户名的cookie,是很不安全的,这行不通,但从数据库的负担考虑,我也不能加入一个简单的无序码而交由我的数据库来进行验证。
  解决的方法是同时设置两个cookie,一个是用户名的cookie,一个是无序码的cookie。这个无序码实际上是由用户名和一个超级密码(只有程序设计者知道)组合通过md5()函数运算产生的。由于md5()是一个单向的无序码,因此是不可以破解的。在用户更改email时,我也可以用该email和超级密码产生一个无序码,以让用户确认修改。这实际上是一个公匙/私匙类的系统。不明白?不要紧,下面再慢慢说明。
  有趣的是,这个系统的扩展能力是可以达到无穷的,因为该系统的主要工作是计算md5()函数的值,而且由web服务器完成,在负载增加时,可以加入其它的服务器来分担负载,虽然认证系统不会拖跨一个数据库,但是这样做就让最终的瓶颈只能出现在数据库上。
  以下是该库中的两个函数--记号产生和记号认证函数。
    <?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://已经进行无序码的检测了吗
     file://如果是的话,返回该变量
     if ( isset($LOGGED_IN) ) {
      return $LOGGED_IN;
      }
     file://are both cookies present?
     if ($user_name && $id_hash) {
     /*
      由cookies中得来的用户名和系统超级密码产生一个认证用的无序码如果该无序码与cookie中的无序码一样,则cookies中的变量是可信的,用户已经登录
     */
      $hash=md5($user_name.$hidden_hash_var);
      if ($hash == $id_hash) {
       file://无序码符合,设置一个全局变量,这样我们在再次调用该函数的时候,
       file://就无需再次进行md5()运算
       $LOGGED_IN=true;
       return true;
      } else {
       file://两个无序码不符合,没有登录
       $LOGGED_IN=false;
       return false;
      }
      } else {
       $LOGGED_IN=false;
       return false;
       }
      }
    function user_set_tokens($user_name_in) {
     /*
      一旦用户名和密码通过验证,就调用这个函数
     */
     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://使用用户名和超级密码创建一个无序码,作判断是否已经登录用
      $id_hash= md5($user_name.$hidden_hash_var);
      file://设置cookies的有效期为一个月,可设置为任何的值
      setcookie('user_name',$user_name,(time()+2592000),'/','',0);
      setcookie('id_hash',$id_hash,(time()+2592000),'/','',0);
     }
   ?>
  再来看另一段有趣的代码,用户怎样才能安全地改变他们的email地址呢?他们可以在任何时候改变email地址,但是要进行确认。
<!-- 分页 -->

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-362594-1-1.html 上篇帖子: PHP和jQuery实现截图自定义头像 下篇帖子: 给图片添加文字(支持中文) // PHP函数
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表