Please criticize as thoroughly as possible, even the smallest thing will be very useful for me.
I'm trying to create a safe and easy system to change for future projects. I am aware that it should have a lot more functionality (check email, access attempts, notification by email, etc.), but this is what I have at the moment. I am wondering if it is safe even now.
I want to continue working on it but I am not 100% sure if I'm on the right track or if I need to add or remove some code (I like it to be as short as possible).
login.sql
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
-- Database: `login`
-- Table structure for table `users`
CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(15) NOT NULL,
`user_email` varchar(40) NOT NULL,
`user_pass` varchar(255) NOT NULL,
`joining_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
config.php
<?php
// Other settings
session_start();
// Connect to the database
class Database {
private $host = "localhost";
private $db_name = "login";
private $username = "root";
private $password = "";
public $conn;
public function dbConnection() {
$this->conn = null;
try {
$this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $exception) {
echo "Connection error: " . $exception->getMessage();
}
return $this->conn;
}
}
// Functions for managing users
class USER {
private $conn;
public function __construct() {
$database = new Database();
$db = $database->dbConnection();
$this->conn = $db;
}
public function runQuery($sql) {
$stmt = $this->conn->prepare($sql);
return $stmt;
}
public function register($uname,$umail,$upass) {
try {
$new_password = password_hash($upass, PASSWORD_DEFAULT);
$stmt = $this->conn->prepare("INSERT INTO users(user_name,user_email,user_pass) VALUES(:uname, :umail, :upass)");
$stmt->bindparam(":uname", $uname);
$stmt->bindparam(":umail", $umail);
$stmt->bindparam(":upass", $new_password);
$stmt->execute();
return $stmt;
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
public function doLogin($uname,$umail,$upass) {
try {
$stmt = $this->conn->prepare("SELECT user_id, user_name, user_email, user_pass FROM users WHERE user_name=:uname OR user_email=:umail ");
$stmt->execute(array(':uname'=>$uname, ':umail'=>$umail));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
if($stmt->rowCount() == 1) {
if(password_verify($upass, $userRow['user_pass'])) {
$_SESSION['user_session'] = $userRow['user_id'];
return true;
} else {
return false;
}
}
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
public function is_loggedin() {
if(isset($_SESSION['user_session'])) {
return true;
}
}
public function redirect($url) {
header("Location: $url");
exit;
}
public function doLogout() {
unset($_SESSION['user_session']);
return true;
}
}
?>
index.php
<?php
require_once('assets/config.php');
// If you are not logged, redirects to login page.
$session = new USER();
if(!$session->is_loggedin()) {$session->redirect('login.php');}
$auth_user = new USER();
$user_id = $_SESSION['user_session'];
$stmt = $auth_user->runQuery("SELECT * FROM users WHERE user_id=:user_id");
$stmt->execute(array(":user_id"=>$user_id));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
?>
<html>
<head>
<meta charset="utf-8">
<title>Welcome</title>
<link href="assets/styles.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Hello, <?php echo $userRow['user_name'];?>! - <a href="logout.php">Logout</a></h1>
<hr/>
<p>This is the user area, this content is private.</p>
</div>
</body>
</html>
login.php
<?php
require_once('assets/config.php');
$login = new USER();
if($login->is_loggedin()!="") {
$login->redirect('index.php');
}
if(isset($_POST['btn-login'])) {
$uname = strip_tags($_POST['txt_uname_email']);
$umail = strip_tags($_POST['txt_uname_email']);
$upass = strip_tags($_POST['txt_password']);
if($login->doLogin($uname,$umail,$upass)) {
$login->redirect('index.php');
} else {
$error = "Wrong Details!";
}
}
?>
<html>
<head>
<meta charset="utf-8">
<title>Login</title>
<link href="assets/styles.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Login or <a href="register.php">Register</a></h1>
<hr/>
<div class="error">
<?php
if(isset($error)) {
echo "<p class='error'>$error</p>";
}
if(isset($_GET['joined'])) {
echo "<p class='success'>Successfully registered please login</p>";
}
?>
</div>
<form method="post" id="login-form">
<input type="text" name="txt_uname_email" placeholder="Username or Email"/>
<input type="password" name="txt_password" placeholder="Password" />
<button type="submit" name="btn-login">Login</button>
</form>
</div>
</body>
</html>
register.php
<?php
require_once('assets/config.php');
$user = new USER();
if($user->is_loggedin()!="") {
$user->redirect('index.php');
}
if(isset($_POST['btn-signup'])) {
$uname = strip_tags($_POST['txt_uname']);
$umail = strip_tags($_POST['txt_umail']);
$upass = strip_tags($_POST['txt_upass']);
if($uname=="") {
$error[] = "Provide username!";
}
else if($umail=="") {
$error[] = "Provide email!";
}
else if(!filter_var($umail, FILTER_VALIDATE_EMAIL)) {
$error[] = 'Please enter a valid email address!';
}
else if($upass=="") {
$error[] = "Provide password!";
}
else if(strlen($upass) < 6){
$error[] = "Password must be atleast 6 characters!";
} else {
try {
$stmt = $user->runQuery("SELECT user_name, user_email FROM users WHERE user_name=:uname OR user_email=:umail");
$stmt->execute(array(':uname'=>$uname, ':umail'=>$umail));
$row=$stmt->fetch(PDO::FETCH_ASSOC);
if($row['user_name']==$uname) {
$error[] = "Sorry username already taken!";
} else if($row['user_email']==$umail) {
$error[] = "Sorry email id already taken!";
} else {
if($user->register($uname,$umail,$upass)){
$user->redirect('login.php?joined');
}
}
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
}
?>
<html>
<head>
<meta charset="utf-8">
<title>Register</title>
<link href="assets/styles.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Register or <a href="login.php">Login</a></h1>
<hr/>
<?php
if(isset($error)) {
foreach($error as $error) {
echo "<p class='error'>$error</p>";
}
}
?>
<form method="post">
<input type="text" name="txt_uname" placeholder="Username" value="<?php if(isset($error)){echo $uname;}?>" />
<input type="text" name="txt_umail" placeholder="Email" value="<?php if(isset($error)){echo $umail;}?>" />
<input type="password" name="txt_upass" placeholder="Password" />
<button type="submit" name="btn-signup">Register</button>
</form>
</div>
</body>
</html>
logout.php
<?php
require_once('assets/config.php');
$user_logout = new USER();
$user_logout->doLogout();
$user_logout->redirect('index.php');
?>