iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 18
2
Modern Web

寫給朋友的 PHP 從 0 到 100 實戰教程系列 第 18

Day 18. PHP教程: 實作登入與登出機制

今天來實作登入頁跟登入後的動作

route.php

switch($route->getParameter(1)){
    case "logout";
      unset($_SESSION['memberID']);
      unset($_SESSION['username']);
      header('Location: login');
    break;
    case "home";
      if(UserVeridator::isLogin(isset($_SESSION['username'])?$_SESSION['username']:'')){
        include('view/header/default.php'); // 載入共用的頁首
        include('view/body/home.php');     // 載入登入用的頁面
        include('view/footer/default.php'); // 載入共用的頁尾
      }else{
        header('Location: logout');
      }
    break;
    case "login";
      if(isset($_POST['submit'])) 
      {
        $gump = new GUMP();

        $_POST = $gump->sanitize($_POST); 

        $validation_rules_array = array(
          'username'    => 'required|alpha_numeric|max_len,20|min_len,3',
          'password'    => 'required|max_len,20|min_len,3'
        );
        $gump->validation_rules($validation_rules_array);

        $filter_rules_array = array(
          'username' => 'trim|sanitize_string',
          'password' => 'trim',
        );
        $gump->filter_rules($filter_rules_array);

        $validated_data = $gump->run($_POST);

        if($validated_data === false) {
          $error = $gump->get_readable_errors(false);
        } else {
          // validation successful
          foreach($validation_rules_array as $key => $val) {
            ${$key} = $_POST[$key];
          }
          $userVeridator = new UserVeridator();
          $userVeridator->loginVerification($username, $password);
          $error = $userVeridator->getErrorArray();

          if(count($error) == 0){
            $condition = "username = :username";
            $order_by = "1";
            $fields = "*";
            $limit = "LIMIT 1";
            $data_array = array(":username" => $username);
            $result = Database::get()->query("members", $condition, $order_by, $fields, $limit, $data_array);
            $_SESSION['memberID'] = $result[0]['memberID'];
            $_SESSION['username'] = $username;
            header('Location: home');
          }
        }
      }
      include('view/header/default.php'); // 載入共用的頁首
      include('view/body/login.php');     // 載入登入用的頁面
      include('view/footer/default.php'); // 載入共用的頁尾
    break;
}

準備登入用的表單

view/body/login.php

<div class="container">

	<div class="row">

	    <div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
			<form role="form" method="post" action="" autocomplete="off">
				<h2>Please Login</h2>
				<p><a href='./'>Back to home page</a></p>
				<hr>

				<?php
				//check for any errors
				if(isset($error)){
					foreach($error as $error){
						echo '<p class="bg-danger">'.$error.'</p>';
					}
				}

				if(isset($_GET['action'])){

					//check the action
					switch ($_GET['action']) {
						case 'active':
							echo "<h2 class='bg-success'>Your account is now active you may now log in.</h2>";
							break;
						case 'reset':
							echo "<h2 class='bg-success'>Please check your inbox for a reset link.</h2>";
							break;
						case 'resetAccount':
							echo "<h2 class='bg-success'>Password changed, you may now login.</h2>";
							break;
					}

				}

				
				?>

				<div class="form-group">
					<input type="text" name="username" id="username" class="form-control input-lg" placeholder="User Name" value="<?php if(isset($error)){ echo htmlspecialchars($_POST['username'], ENT_QUOTES); } ?>" tabindex="1">
				</div>

				<div class="form-group">
					<input type="password" name="password" id="password" class="form-control input-lg" placeholder="Password" tabindex="3">
				</div>
				
				<div class="row">
					<div class="col-xs-9 col-sm-9 col-md-9">
						 <a href='reset'>Forgot your Password?</a>
					</div>
				</div>
				
				<hr>
				<div class="row">
					<div class="col-xs-6 col-md-6"><input type="submit" name="submit" value="Login" class="btn btn-primary btn-block btn-lg" tabindex="5"></div>
				</div>
			</form>
		</div>
	</div>



</div>

準備好登入後的頁面

view/body/home.php

<div>
    登入成功!
    <a href="logout">登出</a>
</div>

UserVeridator 需要新增兩個 function

  • 驗證是否已登入的靜態方法 isLogin
  • 驗證帳號密碼是否正確可登入的 loginVerification 它會用到 Password 物件

validators/UserVeridator.php

<?php
/**
 * 耦合使用 Database 物件進行資料庫驗證 username 與 email 是否已存在於資料庫
 */
class UserVeridator {

    private $error;

    /**
     * 驗證是否已登入
     */
    public static function isLogin($username){
        if($username != ''){
            return true; 
        } else{
            return false; 
        }
    }

    /**
     * 可取出錯誤訊息字串陣列
     */
    public function getErrorArray(){
        return $this->error;
    }

    /**
     * 驗證二次密碼輸入是否相符
     */
    public function isPasswordMatch($password, $passwrodConfirm){
		if ($password != $passwrodConfirm){
            $this->error[] = 'Passwords do not match.';
            return false;
        }
		return true;
    }

    /**
     * 驗證帳號密碼是否正確可登入
     */
    public function loginVerification($username, $password){
        $result = Database::get()->execute('SELECT * FROM members WHERE username = :username', array(':username' => $username));
        if(isset($result[0]['memberID']) and !empty($result[0]['memberID'])) {
            $passwordObject = new Password();
            if($passwordObject->password_verify($password,$result[0]['password'])){
                return true;
            }
        }
        $this->error[] = 'Wrong username or password or your account has not been activated.';
        return false;
    }

    /**
     * 驗證帳號是否已存在於資料庫中
     */
    public function isUsernameDuplicate($username){
        $result = Database::get()->execute('SELECT username FROM members WHERE username = :username', array(':username' => $username));
        if(isset($result[0]['username']) and !empty($result[0]['username'])){
          $this->error[] = 'Username provided is already in use.';
          return false;
        }
		return true;
    }

    /**
     * 驗證信箱是否已存在於資料庫中
     */
    public function isEmailDuplicate($email){
        $result = Database::get()->execute('SELECT email FROM members WHERE email = :email', array(':email' => $email));
        if(isset($result[0]['email']) AND !empty($result[0]['email'])){
            $this->error[] = 'Email provided is already in use.';
            return false;
        }
		return true;
    }   
}

上一篇
Day 17. PHP教學: 實作註冊流程
下一篇
Day 19. PHP教程: 實作收信開通帳號機制
系列文
寫給朋友的 PHP 從 0 到 100 實戰教程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言