Login session control

  • mindfullsilence
  • Professor
  • Professor
  • User avatar
  • Posts: 854

Post 3+ Months Ago

I've been dealing with this mayhem for about a week now. I'm taking php in college this semester and can't seem to figure out how to get a reliable login script to work. The focus of the course is the MVC framework and interacting with the server via PDO.

So far I have the following for my models, views and controllers (dumbed down to show the important bits):

File Structure
  • /app
    • index.php
    • /view
      • admin-panel.php
      • header.php
      • footer.php
    • /model
      • database.php
    • /login
      • index.php
      • /model
        • user.php
      • /view
        • login.php

My /app/index.php :
PHP Code: [ Select ]
session_start();
if (!isset($_SESSION['admin']) || $_SESSION != 1) {
header ("Location: ./login");
}
 
//logged in
include 'view/header.php';
require 'model/database_db.php';
include 'view/panel.php';
require_once 'view/footer.php';
?>
 
  1. session_start();
  2. if (!isset($_SESSION['admin']) || $_SESSION != 1) {
  3. header ("Location: ./login");
  4. }
  5.  
  6. //logged in
  7. include 'view/header.php';
  8. require 'model/database_db.php';
  9. include 'view/panel.php';
  10. require_once 'view/footer.php';
  11. ?>
  12.  


app/login/index.php
PHP Code: [ Select ]
<?php
 
// if already logged in
session_start();
 
echo $_SESSION['admin'];
//////////////////////////////
// Do loggin stuff         //
//////////////////////////////
// get action
if(isset($_POST['action']))
{
   $action = $_POST['action'];
}
else
{
   $action = 'none';
}
$action = strtolower($action);
require_once '../model/database_db.php';
require_once 'model/user.php';
if(is_object($user)) {
   $user->logout();
   
}
switch($action) {
   case 'none':
      include '../view/header.php';
      include 'view/login.php';
      include '../view/footer.php';
      break;
   case 'login':
      $user = new User();
      $user->set_params($_POST);
      $user->login();
      if($user->has_errors())
      {
         include '../view/header.php';
         include 'view/login.php';
         include '../view/footer.php';
      }
      else {
         include '../view/header.php';
         include '../view/panel.php';
         include '../view/footer.php';
      }
      break;
   case 'logout':
      $user->logout();
      echo 'you logged out';
      header('Location: ./');
      break;
}
?>
 
  1. <?php
  2.  
  3. // if already logged in
  4. session_start();
  5.  
  6. echo $_SESSION['admin'];
  7. //////////////////////////////
  8. // Do loggin stuff         //
  9. //////////////////////////////
  10. // get action
  11. if(isset($_POST['action']))
  12. {
  13.    $action = $_POST['action'];
  14. }
  15. else
  16. {
  17.    $action = 'none';
  18. }
  19. $action = strtolower($action);
  20. require_once '../model/database_db.php';
  21. require_once 'model/user.php';
  22. if(is_object($user)) {
  23.    $user->logout();
  24.    
  25. }
  26. switch($action) {
  27.    case 'none':
  28.       include '../view/header.php';
  29.       include 'view/login.php';
  30.       include '../view/footer.php';
  31.       break;
  32.    case 'login':
  33.       $user = new User();
  34.       $user->set_params($_POST);
  35.       $user->login();
  36.       if($user->has_errors())
  37.       {
  38.          include '../view/header.php';
  39.          include 'view/login.php';
  40.          include '../view/footer.php';
  41.       }
  42.       else {
  43.          include '../view/header.php';
  44.          include '../view/panel.php';
  45.          include '../view/footer.php';
  46.       }
  47.       break;
  48.    case 'logout':
  49.       $user->logout();
  50.       echo 'you logged out';
  51.       header('Location: ./');
  52.       break;
  53. }
  54. ?>
  55.  


app/login/model/user.php
PHP Code: [ Select ]
<?php
class User {
   public $error = array();
   private $un;
   private $pass;
   public function __construct() {}
   
   public function set_params($login_info) {
     
      if(count($login_info) > 3) {
         session_destroy();
         $_SESSION = array();
         login_error('Too many inputs, are you a bot?');
      }
     
      else {
         $this->un = $login_info['username'];
         $this->pass = $login_info['password'];
      }
     
   }
   
   private function login_error($message) {
      array_push($this->error,$message);
   }
   
   public function has_errors() {
      $er;
      if($this->error > 0) {
         foreach($this->error as $m) {
            $er .= '<span>' . $m . '</span>';
         }
         return $er;
      }
      else {
         return false;
      }
   }
   
   
   public function login() {
      $db = Database::getDB();
      $q = "SELECT * from admin where ad_username='$this->un' AND ad_password='$this->pass'";
      $query = $db->query($q);
      if($query->fetch() > 0) {
         $_SESSION['admin'] = 1;
         session_start();
      }
      else {
         $this->login_error('Your username or password was incorrect');
      }
   }
   
   public function logout() {
      $_SESSION = array();
      session_destroy();
   }
}
 
?>
 
  1. <?php
  2. class User {
  3.    public $error = array();
  4.    private $un;
  5.    private $pass;
  6.    public function __construct() {}
  7.    
  8.    public function set_params($login_info) {
  9.      
  10.       if(count($login_info) > 3) {
  11.          session_destroy();
  12.          $_SESSION = array();
  13.          login_error('Too many inputs, are you a bot?');
  14.       }
  15.      
  16.       else {
  17.          $this->un = $login_info['username'];
  18.          $this->pass = $login_info['password'];
  19.       }
  20.      
  21.    }
  22.    
  23.    private function login_error($message) {
  24.       array_push($this->error,$message);
  25.    }
  26.    
  27.    public function has_errors() {
  28.       $er;
  29.       if($this->error > 0) {
  30.          foreach($this->error as $m) {
  31.             $er .= '<span>' . $m . '</span>';
  32.          }
  33.          return $er;
  34.       }
  35.       else {
  36.          return false;
  37.       }
  38.    }
  39.    
  40.    
  41.    public function login() {
  42.       $db = Database::getDB();
  43.       $q = "SELECT * from admin where ad_username='$this->un' AND ad_password='$this->pass'";
  44.       $query = $db->query($q);
  45.       if($query->fetch() > 0) {
  46.          $_SESSION['admin'] = 1;
  47.          session_start();
  48.       }
  49.       else {
  50.          $this->login_error('Your username or password was incorrect');
  51.       }
  52.    }
  53.    
  54.    public function logout() {
  55.       $_SESSION = array();
  56.       session_destroy();
  57.    }
  58. }
  59.  
  60. ?>
  61.  

app/login/view/login.php
PHP Code: [ Select ]
<div id="login">
<h1>Please Login</h1>
<?php
if(is_object($user) && $user->has_errors())
echo '<div class="error">' . $user->has_errors() . '</div>';
?>
<form method="post" action=".">
<input type="text" name="username">
<input type="password" name="password">
<input type="hidden" name="action" value="login" />
<button type="submit">Login</button>
</form>
</div>
 
  1. <div id="login">
  2. <h1>Please Login</h1>
  3. <?php
  4. if(is_object($user) && $user->has_errors())
  5. echo '<div class="error">' . $user->has_errors() . '</div>';
  6. ?>
  7. <form method="post" action=".">
  8. <input type="text" name="username">
  9. <input type="password" name="password">
  10. <input type="hidden" name="action" value="login" />
  11. <button type="submit">Login</button>
  12. </form>
  13. </div>
  14.  


When I click login with a bad username or password, I am redirected to the login page and displayed the error. This is good.

When I click login with a good username and password, I am directed to the "app/index.php". Also good

I am unable to logout. When I click my "logout" button that I've set up in my header, the $_SESSION['admin'] is not destroyed.
Also, If I destroy the session and then type in the location of my "app/index.php" location into the browser, I am able to get to the admin panel even though I am not logged in.

I ran the "logout" function on my $user object (instantiation of the User class in "app/login/model/user.php") to clear my $_SESSION variables and then tried to echo out $_SESSION['admin']. I'm getting "1" which tells me the $_SESSION variables aren't getting cleared, which I'm guessing is why I can get to the admin page without logging in.
  • Anonymous
  • Bot
  • No Avatar
  • Posts: ?
  • Loc: Ozzuland
  • Status: Online

Post 3+ Months Ago

  • natas
  • PHP Ninja
  • Proficient
  • natas
  • Posts: 308
  • Loc: AFK

Post 3+ Months Ago

In your "/app/index.php" on line 2, what does

Code: [ Select ]
$_SESSION != 1


actually check for?

I've never used that before and just curious.
  • natas
  • PHP Ninja
  • Proficient
  • natas
  • Posts: 308
  • Loc: AFK

Post 3+ Months Ago

Did you try using

unset($_SESSION['admin']);

EDIT:

or

session_unset();
  • mindfullsilence
  • Professor
  • Professor
  • User avatar
  • Posts: 854

Post 3+ Months Ago

Hey guys, I got it working so I figured I'd share. Was pretty simple really, if you take a look at my "app/login/view/login.php" script you'll notice at the end that theere is a logout function. Well, this doesn't do a whole lot of good when calling it on an object if I'm on a seperate page that hasn't instantiated the object yet. Basically, I hadn't shared the object across my scripts as a global, so after being redirected to the admin page once logged in, the $user object was destroyed. So when I clicked logout, I was taken to my login page and tried calling the "logout" function on an object that no longer existed. I ended up just sticking "unset($_SESSION['admin']) inside my login controller instead of inside the class. Hope that makes sense, if not and someone needs to better understand, let me know and I'll post some code.
  • this213
  • Guru
  • Guru
  • User avatar
  • Posts: 1260
  • Loc: ./

Post 3+ Months Ago

Glad you got it fixed, however....

You should only be using PHP built in sessions as a temporary solution. Anyone with access to the server can pretty much do whatever they want with them, including change their location or read them outright. This goes quadruple for anyone writing code on a shared host with multiple web sites.

A much better solution is to just generate a random string and set that as a cookie as well as store it in your database along with various client info such as user agent, timestamp and so on. You can then make a second table to store any session variables you might want, which may include user id, option settings and so on. When you destroy a session like this, you set the cookie to some nonsense value and remove the rows from those tables that are keyed to that random string and there is no possible way a user could still be logged in. This gives you far more control in authenticating a session because now you can do things like making sure the user is still using the same browser they logged in with, or ensuring a user is only logged in from one location.
  • mindfullsilence
  • Professor
  • Professor
  • User avatar
  • Posts: 854

Post 3+ Months Ago

Huh, I would have never thought of that. I might revisit this thread later down the road to ask how to implement such a method. For now, this is a simple school project so i don't think I need to worry too much about security for now. I have a very small understanding of PHP right now but am slowly getting it - and I'm still lightyears ahead of the rest of my class so I doubt my instructor will go too deep into security issues. He didn't even encrypt the passwords for the database because the idea of converting a form value to a jumble of characters was too much for the class to understand. The students inability to comprehend neither the how nor the why astounded me. Point is, I'm sure I'll still have an incredible amount of material to learn post-graduation.

Post Information

  • Total Posts in this topic: 6 posts
  • Users browsing this forum: No registered users and 74 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
cron
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.