Scripts

Eenvoudig login systeem

Dit is een eenvoudig login systeem met de nodige beveiligingen. Het systeem is ontwikkeld m.b.v. een MVC-structuur en een router.

mapstructuur.txt
Hoofdmap

/model
	.Login.php
/view
	404.php
	logged-in-page.php
	login.php
/ctrl
	404CTRL.php
	LoggedInCTRL.php
	LoginCTRL.php
/inc
	confic.php
	header.php
	footer.php
/style
	style.css
.htaccess
index.php
router.php
database-user.sql
htaccess.txt
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
database-user.sql
CREATE TABLE `user` (
  `id`        int(8) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(150) NOT NULL DEFAULT '',
  `pass`      varchar(255) NOT NULL,
  `email`     varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
config.php
<?php
	
	Database gegevens voor connectie
    define("HOST", 'localhost');
    define("NAME", 'login');
    define("PASS", '');
    define("USER", 'root');
    
    class Connect{
        public static function connect(){
            try{
                $opts = [
                    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES   => false,
                ];
                return new PDO('mysql:host=' . HOST .';dbname=' . NAME . ';charset=utf8', USER, PASS, $opts);
            }
            catch(PDOException $e){
                //throw new PDOException($e->getMessage(), (int)$e->getCode());
                return 'Something get wrong!';
            }
        }
    }

?>
index.php
<?php require_once 'router.php'; ?>
router.php
<?php
// Start beveiligde sessie
session_set_cookie_params(['httponly' => true, 'secure' => true]);
session_start();
session_regenerate_id(true);

// Uitloggen
function logout(){
	session_destroy();
	setcookie('auth_token', "", time() - 3600);
	header('Location: login');
	exit;
}

// Stel GEBRUIKERS-IP en GEBRUIKERS-AGENT in
if(!isset($_SESSION['ip'])) $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
if(!isset($_SESSION['ua'])) $_SESSION['ua'] = $_SERVER['HTTP_USER_AGENT'];

// Uitloggen wanneer het GEBRUIKERS-IP en de GEBRUIKERS-AGENT niet gelijk zijn aan het werkelijke GEBRUIKERS-IP en de GEBRUIKERS-AGENT
if($_SESSION['ip'] != $_SERVER['REMOTE_ADDR'] || $_SESSION['ua'] != $_SERVER['HTTP_USER_AGENT']){
	logout();
}

// Haal de URL voor de ROUTER op
$url = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$urlSegments = explode('/', trim($url, '/'));
$action = !empty($urlSegments[1]) ? $urlSegments[1] : 'login';

// Een lijst met beschikbare pagina's voor wanneer de gebruiker niet is ingelogd
$allowed_actions = ['login'];

// Stuur de gebruiker door naar de homepage als deze niet is ingelogd of als de pagina niet in de $allowed_actions-lijst staat
if(!in_array($action, $allowed_actions) && !isset($_COOKIE['auth_token'], $_SESSION['auth_token'])){
    header('Location: login');
    exit;
}
// Als het COOKIE-token niet overeenkomt met het SESSION-token, wordt de gebruiker uitgelogd
else if(isset($_COOKIE['auth_token'], $_SESSION['auth_token']) && $_COOKIE['auth_token'] !== $_SESSION['auth_token']){
	logout();
}
else{
	require_once 'inc/config.php';
	
	// De ROUTER
	switch($action){
		case 'login':
			require_once 'model/Login.php';
			require_once 'ctrl/LoginCTRL.php';
			$ctrl = new LoginCTRL;
			break;
		case 'redirect-login':
			header('Location: login');
			exit;
		case 'logged-in-page':
			require_once 'ctrl/LoggedInCTRL.php';
			$ctrl = new LoggedInCTRL;
			break;
		case 'logout':
			logout();
		default:
			require_once 'ctrl/404CTRL.php';
			$ctrl = new notFoundCTRL;
			break;
	}
	$ctrl->pageControl();
}

?>
LoginCTRL.php
<?php

	class LoginCTRL{
        private $title, $h1;
		
		function __construct(){
			$this->title = $this->h1 = 'Login page';
		}
		
		public function pageControl(){
			// Als de gebruiker al is ingelogd, wordt de gebruiker doorgestuurd naar de logged-in-page pagina
			if(isset($_COOKIE['auth_token'], $_SESSION['auth_token'])){
				header('Location: logged-in-page');
				exit;
			}
			if(isset($_POST['email'], $_POST['pass']) && !empty($_POST['email']) && !empty($_POST['pass'])){
				$email = filter_var(trim($_POST['email']), FILTER_SANITIZE_EMAIL);
				$pass  = filter_var(trim($_POST['pass']),  FILTER_SANITIZE_STRING);
				
				$new_login = new Login;
				$new_login->login($email,$pass);
			}
			require_once 'view/login.php';
		}
    }
    
?>
Login.php
<?php

	class Login{
		private $db;
		
		function __construct(){
			$this->db = Connect::connect();
		}
		
        public function login($email,$pass){
			$stmt = $this->db->prepare("SELECT * FROM user WHERE email = ?");
			$stmt->execute([$email]);
			$result = $stmt->fetch(PDO::FETCH_ASSOC);
			
			if($result){
				// WACHTWOORD is gemaakt met password_hash($password, PASSWORD_DEFAULT)
				if(password_verify($pass, $result['pass'])){
					// Maak een token
					$token = base64_encode(random_bytes(64));
					$token = strtr($token, '+/', '-_');
					
					// Zet $token in een COOKIE en SESSIE
					setcookie('auth_token', $token, time() + 3600, '/');
					$_SESSION['auth_token'] = $token;
					
					// Zet de gebruikersgegevens in een sessie
					$_SESSION['id'] = htmlspecialchars($result['id']);
					$_SESSION['user_name'] = htmlspecialchars($result['user_name']);
					
					// VERWIJS de GEBRUIKER door naar de ingelogde pagina
					header('Location: logged-in-page');
					exit;
				}
				else{
					$_SESSION['note'] = '<div class="note">Uw inloggegevens komen niet overeen!</div> ';
					header('Location: redirect-login');
					exit;
				}
			}
			else{
				$_SESSION['note'] = '<div class="note">Uw inloggegevens komen niet overeen!</div>';
				header('Location: redirect-login');
				exit;
			}
		}
    }
    
?>
login.php
<?php require_once 'inc/header.php'; ?>
	<h1><?php echo $this->h1; ?></h1>
	<form action="login" method="post">
		<?php
			if(isset($_SESSION['note'])){
				echo $_SESSION['note'];
				unset($_SESSION['note']);
			}
		?>
		<label for="exampleInputEmail1">E-mail adres</label>
		<input type="email" name="email" required>
		<label>Wachtwoord</label>
		<input type="password" name="pass" required>
		<button type="submit" class="btn btn-primary">Inloggen</button>
	</form>
</div>
<?php require_once 'inc/footer.php'; ?>
LoggedInCTRL.php
<?php

	class LoggedInCTRL{
        private $title, $h1;
		
		function __construct(){
			$this->title = $this->h1 = 'Logged in page';
		}
		
		public function pageControl(){
			require_once 'view/logged-in-page.php';
		}
    }
    
?>
logged-in-page.php
<?php
	require_once 'inc/header.php'; 
	
	echo '<h1>' . $this->h1 . '</h1>';
	echo 'Welkom ' . $_SESSION['user_name'] . '!<br>Je bent nu ingelogd.';
	echo '<br><a href="logout">Uitloggen</a>';
	require_once 'inc/footer.php';
?>
404CTRL.php
<?php

	class notFoundCTRL{
        private $title, $h1;
		
		function __construct(){
			$this->title       = '404 Pagina niet gevonden!';
			$this->h1          = '404 Fout: Pagina niet gevonden!';
		}
		
		public function pageControl(){
			require_once 'view/404.php';
		}
    }
    
?>
404.php
<?php
	http_response_code(404);
	
	require_once 'inc/header.php';

	echo '<h1>' . $this->h1 . '</h1>';

    require_once 'inc/footer.php';
?>
header.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset=UTF-8>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="style/style.css">
	<title><?php echo $this->title; ?></title>
</head>
<body>
footer.php
</body>
</html>
style.css
body{
    margin: 0;
    text-align: center;
    font-family: calibri;
    background: #f4f4f4;
    font-size: 16px;
}
form{
    width: 400px;
    margin: 0 auto;
    background: #fff;
    padding: 15px;
    box-sizing: border-box;
    border-radius: 5px;
    box-shadow: 0 0 5px #aaa;
}
form label, form input{
    width: 100%;
    box-sizing: border-box;
}
form label{
    display: block;
    text-align: left;
}
form input[type=email], form input[type=password]{
    line-height: 30px;
    height: 30px;
    padding: 0 8px;
    margin-bottom: 10px;
}

Reacties

0
Nog geen reacties.