1

我试图在与数据库连接的 php 中创建一个用户类这是我到目前为止编写的类!

class db {
    private function conn(){
        set_exception_handler(create_function('$e','db::db_error($e);'));
        return new PDO('mysql:host=localhost;dbname=mydb','admin','pass');  //Persistent connection without closing conn: ....$user, $pass, array(PDO::ATTR_PERSISTENT=>true));
    }
    public static function db_error($log){
        $mylog=$_SERVER['REMOTE_ADDR']." - ".$_SERVER['PHP_SELF']." - ".date("d/m/Y h:i:s")." - ".$log;
        $showlog=$_SERVER['REMOTE_ADDR']." - Internal Server Error!";
        // $mylog > error information log on db or file!
        exit($showlog);
    }
    public function dbconstruction(){
        $pdo=$this->conn();
        $pdo->query("CREATE TABLE IF NOT EXISTS `users` (
                `uid` text NOT NULL,
                `sid` text NOT NULL,
                `did` text NOT NULL,
                `username` text NOT NULL,
                `password` text NOT NULL,
                `fullname` text NOT NULL,
                `email` text NOT NULL,
                `birthday` text NOT NULL,
                `expire` text NOT NULL
            ) DEFAULT CHARSET=latin1;");
        $pdo->query("CREATE TABLE IF NOT EXISTS `unverified` (
                `uid` text NOT NULL,
                `token` text NOT NULL,
                `expire` text NOT NULL
            ) DEFAULT CHARSET=latin1;");
        $pdo->query("CREATE TABLE IF NOT EXISTS `sessions` (
                `uid` text NOT NULL,
                `session` text NOT NULL,
                `expire` text NOT NULL
            ) DEFAULT CHARSET=latin1;");
        $pdo=null;
        return true;
    }
    public function send($a,$t){ // usage:  $db->send(array('username'=>'boss'),'users');
        if(empty($a)||count($a)<1){return false;}
        $keys=array_keys($a);
        $keys2=array_keys($a);
        foreach($keys2 as &$k){$k=':'.$k;} // ":key"
        $params=array_combine($keys2,array_values($a));
        $st=$this->conn()->prepare("INSERT INTO `$t`(".(count($keys)>1?implode(",",$keys):$keys[0]).") VALUES (".(count($keys2)>1?implode(",",$keys2):$keys2[0]).")");
        $st->execute($params);
        if($st){$st=null;return true;}
        $st=null;
        return false;
    }
    public function receive($a,$t){ // usage:  $db->receive(array('username'=>'boss'),'users');
        if(empty($a)||count($a)<1){return false;}
        $keys=array_keys($a);
        $keys2=array_keys($a);
        foreach($keys as &$k){$k=$k.' = :'.$k;} // "key = :key"
        foreach($keys2 as &$k){$k=':'.$k;} // ":key"
        $params=array_combine($keys2,array_values($a));
        $st=$this->conn()->prepare("SELECT * FROM $t WHERE ".(count($keys)>1?implode(" AND ",$keys):$keys[0]));
        $st->execute($params);
        $result=$st->fetchAll();
        $st=null;
        return $result;
    }
    public function remove($a,$t){ // usage:  $db->remove(array('token'=>'boss'),'unverified');
        if(empty($a)||count($a)<1){return false;}
        $keys=array_keys($a);
        $keys2=array_keys($a);
        foreach($keys as &$k){$k=$k.' = :'.$k;} // "key = :key"
        foreach($keys2 as &$k){$k=':'.$k;} // ":key"
        $params=array_combine($keys2,array_values($a));
        $st=$this->conn()->prepare("DELETE FROM $t WHERE ".(count($keys)>1?implode(" AND ",$keys):$keys[0]));//DELETE FROM `unverified` WHERE token = 'asd'
        $st->execute($params);
        $c=$st->rowCount();
        if($c>0){$st=null;return true;}
        $st=null;
        return false;
    }
    public function update($a,$b,$t){ // usage:  $db->update(array('password'=>'boss'),array('uid'=>$uid),'users'); // update password where uid=$uid
        if(empty($a)||count($a)<1||empty($b)||count($b)<1){return false;}
        $a_keys=array_keys($a);
        foreach($a_keys as &$k){$k=$k.'=?';} // "key=?"
        $set_params=array_values($a);       
        $b_keys=array_keys($b);
        foreach($b_keys as &$k){$k=$k.'=?';} // "key=?"
        $where_params=array_values($b);
        $params=array_merge($set_params,$where_params);
        $set=(count($a_keys)>1?implode(", ",$a_keys):$a_keys[0]);
        $where=(count($b_keys)>1?implode(" AND ",$b_keys):$b_keys[0]);
        $st=$this->conn()->prepare("UPDATE $t SET $set WHERE $where");
        $st->execute($params);
        $c=$st->rowCount();
        if($c>0){$st=null;return true;}
        $st=null;
        return false;
    }
    public function check($a,$t){ // usage:  $db->check(array('username'=>'boss'),'users');
        if(empty($a)||empty($t)||count($a)<1){return false;}
        $keys=array_keys($a);
        $keys2=array_keys($a);
        foreach($keys as &$k){$k=$k.' = :'.$k;} // "key = :key"
        foreach($keys2 as &$k){$k=':'.$k;} // ":key"
        $params=array_combine($keys2,array_values($a));
        $st=$this->conn()->prepare("SELECT * FROM $t WHERE ".(count($keys)>1?implode(" AND ",$keys):$keys[0]));
        $st->execute($params);
        $c=$st->rowCount();
        if($c>0){$st=null;return true;}
        $st=null;
        return false;
    }
}

//$user = new user;
//echo $user->verifyemail('boss','2391cc263bdf0fcf6e69872608ee05fdde7dbdc4');
//echo $user->login('1234567','boss');
//echo $user->register('boss','ad min','1234567','waw1@law.bau','1955');
//$db = new db;
//echo $db->dbconstruction();
//print_r(  $db->update(array('username'=>'thoi'),array('username'=>'asd'),'users')  );


class user { // uid | sid | did | username | password | fullname | email | birthday
    public $settings=array(
                'expire_cookie'=>'4m', // cookie expire time
                'expire_account'=>'3M', // inactivity account expire time
                'expire_verification'=>'1d' // unverified email account expire time
            );
    public function register($username,$fullname,$password,$email,$birthday){  // to add : if is expired register it
        if(empty($username)||empty($fullname)||empty($password)||empty($email)||empty($birthday)
            ||!preg_match('/[a-z0-9\-_]{4,31}/i',$username)
            ||!preg_match('/[a-z\s]{5,64}/i',$fullname)
            ||!preg_match('/(.){7,25}/i',$password)
            ||!preg_match('/([\w\-\._]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/i',$email)
            ||!preg_match('/(19|20)([0-9]{2})/i',$birthday)
          ){return false;}
        $username=strtolower($username);
        $email=strtolower($email);
        $db=new db;
        if($db->check(array('username'=>$username),'users')===true){return 'registered username!';}
        if($db->check(array('email'=>$email),'users')){return 'registered email!';}
        $shadow = $this->shadow($password);
        $id=$this->gen(md5($username.$fullname.$password.$email.$birthday.$shadow)); // $id['uid']  , $id['sid']  , $id['did']
        $register=$db->send(array('uid'=>$id['uid'],'sid'=>$id['sid'],'did'=>$id['did'],'username'=>$username,'password'=>$shadow,'fullname'=>$fullname,'email'=>$email,'birthday'=>$birthday,'expire'=>time_ahead($this->settings['expire_account'])),'users');
        if($register){
            $expire_verify=time_ahead($this->settings['expire_verification']);
            $db->send(array('uid'=>$id['uid'],'token'=>$id['token'],'expire'=>$expire_verify),'unverified');
            // SEND EMAIL WITH url http://site.com/?u=$uid&t=$token  OR  http://site.com/verify  to input manually token
            return 'Success registration! Time to verify is until '.date('d/M/Y H:i:s',$expire_verify);
        }
        return false;
    }
    public function login($password,$user){
        if(empty($password)||empty($user)){return false;}
        $user=strtolower($user);
        $db=new db;
        $user_check=$db->check(array('username'=>$user),'users');
        $email_check=$db->check(array('email'=>$user),'users');
        if(!$user_check&&!$email_check){return 'Invalid username/email';}
        $user_details=$db->receive(array(($user_check?'username':'email')=>$user),'users')[0];
        if($this->pass_verify($password,$user_details['password'])){  //**********   set some cookies with expire time_ahead('2h')
            $uid=$user_details['uid'];
            if($user_details['expire']<time()){
                if(!$this->remove_user($uid)){return 'int err!';}
                return 'Account has been expired on '.date('d M Y h:i',$user_details['expire']).'! Click HERE to register!';
            }else{
                $db->update(array('expire'=>time_ahead($this->settings['expire_account'])),array('uid'=>$uid),'users');
                $session=$this->gen(md5($uid.'18.1"8-18\'18'))['session'];  //$_SERVER["SSL_SESSION_ID"] if $ssl true
                $expire=time_ahead($this->settings['expire_cookie']);


                /*
                session_set_cookie_params ( $lifetime , $path , $domain , $secure , $httponly  );
                setcookie('auth','sdaasdasa',time()+'120',WWW,DOMAIN,$GLOBALS['ssl'],true);

                define('DOMAIN','example.com',true);
                define('WWW',$_SERVER['DOCUMENT_ROOT'],true);
                $ssl=((isset($_SERVER['HTTPS'])&&$_SERVER['HTTPS']=='on')?true:false);

                session_set_cookie_params ( 20 , WWW , DOMAIN , $GLOBALS['ssl'] , true  );
                session_name('auth');
                session_start();
                */
                //   setcookie('auth',$session,$expire);  <---- (-_-)!


                if($db->send(array('uid'=>$uid,'session'=>$session,'expire'=>$expire),'sessions')){
                    print 'session set!';
                }
            }
            $unverified=$db->check(array('uid'=>$uid),'unverified');//check if is in unverifided db
            if($unverified){
                $expire_verify=$db->receive(array('uid'=>$uid),'unverified')[0]['expire'];
                if($expire_verify<time()){ //expired verification via email!
                    if(!$this->remove_user($uid)){return 'int err!';}
                    return 'Verification has expired! Account has been deleted :(';
                }else{
                    //$rem=($expire_verify-time());
                    return 'success login! Unverified account! Remaining time to verify your account is until '.date('d/M/Y H:i:s',$expire_verify).' !!!';
                }
            }else{
                return 'success login! Verified account :)';
            }
            return false;
        }else{
            return 'invalid password!';
        }
        return false;
    }
    public function verifyemail($user,$token){
        if(empty($token)||empty($user)){return false;}
        $user=strtolower($user);
        $db=new db;
        $user_check=$db->check(array('username'=>$user),'users');
        $email_check=$db->check(array('email'=>$user),'users');
        if($user_check||$email_check){
            $uid=$db->receive(array(($user_check?'username':'email')=>$user),'users')[0]['uid'];
            if(!$db->check(array('uid'=>$uid),'unverified')){return 'Already verified!';}
            if($db->check(array('token'=>$token),'unverified')){
                $db->remove(array('token'=>$token),'unverified');
                return 'Verified successfully.';
            }else{return 'invalid token!';}
        }else{return 'invalid user!';}
        return false;
    }
    public function remove_user($uid){
        if(!empty($uid)){
            $db=new db;
            $db->remove(array('uid'=>$uid),'users');
            $db->remove(array('uid'=>$uid),'unverified');
            return true;
        }
        return false;
    }
    public function gen($params){ // generate ids ,  USAGE   gen('user123123123')['did']
        $a = $params.$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_HOST'].$_SERVER['HTTP_USER_AGENT'];
        $r = array(
            'sid' => strtolower( sha1(uniqid(md5($a.time()))) ) , // secret id
            'uid' => strtolower( sha1(md5(uniqid($a.time()))) ) , // public id
            'did' => strtolower( sha1(md5(uniqid($a).time())) ) , // download id
            'token' => strtolower( sha1(md5(uniqid($a).(time()*29.06))) ) , // token id for unverified accounts
            'session' => strtolower( sha1(md5(uniqid($a).(time()*19.91))) ) // login session id
        );
        return $r;
    }
    private function shadow($i){ // usage  shadow('mypass')
        $s='';for($n=0;$n<16;$n++){$s.=chr(rand(1,128));}
        $s='$1$'.md5($s).'$';
        return crypt($i,$s);
    }
    private function pass_verify($pass,$hash){ // usage if($this->pass_verify('Zmypass',$s)){echo 'yes';}else{echo 'no';}
        return ((crypt($pass,$hash)==$hash)?true:false);
    }
}

function time_ahead($t,$c=true){
    if(preg_match('/(\d+)([y|M|d|h|m|s])/',$t,$ti)){
        switch($ti[2]){//1year=365.242144days <-maya says so
            case'y':$r=60*60*24*30.43684991666667*12*$ti[1];break;
            case'M':$r=60*60*24*30.43684991666667*$ti[1];break;
            case'd':$r=60*60*24*$ti[1];break;
            case'h':$r=60*60*$ti[1];break;
            case'm':$r=60*$ti[1];break;
            case's':$r=$ti[1];break;
        }
        return ($c?time()+$r:$r);
    }
    return false;
}

您可以在 dbconstruct func 的代码中看到 db 结构。

我的问题是我应该使用登录/注销:

  • 会话和cookie

  • mysql with table:sessions[uid|session|expire] 和 pcntl_fork 用于清理会话表中的过期会话,称为每次页面重新加载或类似的东西!

我正在考虑使用 ajax 进行登录并刷新

也欢迎任何其他建议。
提前致谢...

4

1 回答 1

1

我的建议是:使用会话。

一个会话仅使用 1 个 cookie: PHPSESSID。所有会话数据都存储在服务器端(因此不可能被篡改)。

用于session_set_save_handler覆盖 PHP 存储其会话数据的位置。让它将数据存储在 MySQL 表中。

会话表中没有uidas 字段。即使是未经身份验证的客人也可以进行会话。uid是会话数据的一部分。而不是uid你想要的sess_id,即。会话的 ID。另一个原因是一个用户可能有两个会话,您不希望它们干扰,因为这可能会打破您对会话如何工作的假设。

expire没问题,用它来实现垃圾回收回调。

次要:考虑使用utf8_general_ci而不是latin1.

于 2013-03-27T16:57:05.213 回答