I have the cookie set and can see it in the console. When I close the browser and re-open it, it shows the cookie is there still , but not the session. So I am trying to see why my code is not keeping the user logged in. I will provide all the files necessary below.
EDIT: I should elaborate on this a little. So when the user close's his/her browser the session should no longer be there, but the cookie should and it is. So once that happens I want to say okay since there is a cookie we will grab that user's cookie look it up in the db and retrieve their id. Then using that id from a sessions table look up the id from the users table and log that user in.
login.php:
<?php
require_once 'core/init.php';
if(Input::exists()) {
if(Token::check(Input::get('token'))) {
$validate = new Validate();
$validation = $validate->check($_POST,array(
'username' => array('required' => true),
'password' => array('required' => true)
));
if($validation->passed()) {
$user = new User();
$remember = (Input::get('remember') === 'on') ? true : false;
$login = $user->login(Input::get('username'), Input::get('password'), $remember);
if($login) {
Redirect::to('index.php');
} else {
echo '<p>Sorry, logging in failed</p>';
}
} else {
foreach($validation->errors() as $error) {
echo $error, '<br>';
}
}
}
}
?>
<form action="" method="post">
<div class="field">
<label for="username">Username</label>
<input type="text" name="username" id="username" autocomplete="off">
</div>
<div class="field">
<label for="password">Password</label>
<input type="password" name="password" id="password" autocomplete="off">
</div>
<div class="field">
<label for="remember">
<input type="checkbox" name="remember" id="remember">Remember Me
</label>
</div>
<input type="hidden" name="token" value="<?php echo Token::generate(); ?>">
<input type="submit" value="Log In">
</form>
init.php:
<?php
session_start();
$GLOBALS['config'] = array(
'mysql' => array(
'host' => '127.0.0.1',
'username' => 'root',
'password' => 'root',
'db' => 'register_login'
),
'remember' => array(
'cookie_name' => 'hash',
'cookie_expiry' => 604800
),
'session' => array(
'session_name' => 'user',
'token_name' => 'token'
)
);
spl_autoload_register(function($class) {
require_once 'classes/' . $class . '.php';
});
require_once 'functions/sanitize.php';
if(Cookie::exists(Config::get('remember/cookie_name')) && !Session::exists(Config::get('session/session_name'))) {
$hash = Cookie::get(Config::get('remember/cookie_name'));
$hashCheck = DB::getInstance()->get('users_session', array('hash', '=', $hash));
if($hashCheck->count()) {
$user = new User($hashCheck->first()->user_id);
$user->login();
}
}
?>
User.php: In this file under the public function login I put echo 'ok', and echo 'not ok' to see if my if was passing and I am getting 'no ok', so the if is not passing true. So my best guess is that $this->exists() is passing false. It should not be passing false though.
<?php
class User {
private $_db,
$_data,
$_sessionName,
$_cookieName,
$_isLoggedIn;
public function __construct($user = null){
$this->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
$this->_cookieName = Config::get('remember/cookie_name');
if(!$user){
if(Session::exists($this->_sessionName)) {
$user = Session::get($this->_sessionName);
if($this->find($user)) {
$this->_isLoggedIn = true;
} else {
}
} else {
$this->find($user);
}
}
}
public function create($table,$fields = array()){
if(!$this->_db->insert($table, $fields)){
throw new Exception('There was a problem creating an account.');
}
}
public function find($user = null) {
if($user){
$field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username = null, $password = null, $remember = false) {
if(!$username && !$password && $this->exists()) {
echo 'Ok';
//Session::put($this->_sessionName, $this->data()->id);
} else {
echo 'no ok';
$user = $this->find($username);
if($user){
if($this->data()->password === Hash::make($password, $this->data()->salt)) {
Session::put($this->_sessionName, $this->data()->id);
if($remember){
$hash = Hash::unique();
$hashCheck = $this->_db->get('users_session', array('user_id', '=', $this->data()->id));
if(!$hashCheck->count()) {
$this->_db->insert('users_session',array(
'user_id' => $this->data()->id,
'hash' => $hash
));
} else {
$hash = $hashCheck->first()->hash;
}
Cookie::put($this->_cookieName, $hash, Config::get('remember/cookie_expiry'));
}
return true;
}
}
}
return false;
}
public function exists() {
return (!empty($this->_data)) ? true: false;
}
public function data(){
return $this->_data;
}
public function isLoggedIn(){
return $this->_isLoggedIn;
}
public function logout(){
$this->_db->delete('users_session', array('user_id' ,'=' , $this->data()->id));
Session::delete($this->_sessionName);
Cookie::delete($this->_cookieName);
}
}
Session.php:
<?php
class Session {
public static function exists($name) {
return(isset($_SESSION[$name])) ? true : false;
}
public static function put($name, $value) {
return $_SESSION[$name] = $value;
}
public static function get($name) {
return $_SESSION[$name];
}
public static function delete($name) {
if(self::exists($name)) {
unset($_SESSION[$name]);
}
}
public static function flash($name, $string = '') {
if(self::exists($name)){
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
Related
I am using an OOP login/register system and I want to apply a session timeout, I've looked at alot of tutorials and all of them explain how to go about it using a normal login/register system only. here are some of my codes:
init.php
session_start();
$GLOBALS['config'] = array(
'mysql' => array(
'host' => '127.0.0.1',
'username' => 'root',
'password' => '',
'db' => 'database'
),
'remember' => array(
'cookie_name' => 'hash',
'cookie_expiry' => '604800'
),
'session' => array(
'session_name' => 'user',
'token_name' => 'token'
)
);
Below are my classes that deal with logging in
Session.php
class Session {
public static function exists($name){
return (isset($_SESSION[$name])) ? true : false;
}
public static function put($name, $value){
return $_SESSION[$name] = $value;
}
public static function get($name){
return $_SESSION[$name];
}
public static function delete($name){
if(self::exists($name)){
unset($_SESSION[$name]);
}
}
public static function flash($name, $string = ''){
if(self::exists($name)){
$session = self::get($name);
return $session;
}else{
self::put($name, $string);
}
}
}
User.php
class User{
private $_db,
$_data,
$_sessionName,
$_isLoggedIn;
public function __construct($user = null) {
$this->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
if(!$user){
if(Session::exists($this->_sessionName)){
$user = Session::get($this->_sessionName);
if($this->find($user)){
$this->_isLoggedIn = true;
}else{
//process logout
}
}
}else{
$this->find($user);
}
}
public function user_password($password = null){
if($this->data()->password === Hash::make($password, $this->data()->salt)){
return true;
}
}
public function find($user = null){
if($user){
$field = (is_numeric($user)) ? 'user_id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count()){
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username = null, $password = null){
$user = $this->find($username);
if($user){
if($this->data()->password === Hash::make($password, $this->data()->salt)){
//This palce is important, change the user_id to the name of the users' table primary key
Session::put($this->_sessionName, $this->data()->user_id);
return true;
}
}
return false;
}
public function hasPermission($key){
$group = $this->_db->get('groups', array('id', '=', $this->data()->group));
if($group->count()){
$permissions = json_decode($group->first()->permissions, true);
if($permissions[$key] == true){
return true;
}
}
return false;
}
public function logout(){
Session::delete($this->_sessionName);
}
public function data(){
return $this->_data;
}
public function isLoggedIn(){
return $this->_isLoggedIn;
}
}
You can add a $_SESSION['timeOfLogin'] = time(); if the login succeeds.
While performing any task you can check if the login is still valid to go on by sending $_SESSION['timeOfLogin'] to the following function
public function sessionIsValid($timeOfLogin){
//Lets say expiry is 1 day
$expiryTime=24*60*60;
//Get the current time
$currentTime = time();
// How much time user has spent
$timeDifference = $currentTime - timeOfLogin;
//If time spent is less than expiry then it is good to go
if($timeDifference < $expiryTime)
return true;
else
return false;
}
I would like to learn programming, so I downloaded a safe script built in OOP to manage the login and user registration, I would like to get their hands to learn this language through classes and objects.
The script is this: https://github.com/aguvasu/Secure-PHP-OOP-user-reg-login-system-with-Boostrap
I come down to it, my problem where I can not find solution is that I would like to create a page where member.php show the list of registered users (username, email, etc.), but do not know how to do.
The class User.php shows this:
class User {
private $_db, $_data, $_sessionName, $_cookieName, $_isLoggedIn;
function __construct($user = null) {
$this->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
$this->_cookieName = Config::get('remember/cookie_name');
if (!$user) {
if (Session::exists($this->_sessionName)) {
$user = Session::get($this->_sessionName);
if ($this->find($user)) {
$this->_isLoggedIn = true;
} else {
//logout
}
}
} else {
$this->find($user);
}
}
public function find($user = null) {
if ($user) {
$field = (is_numeric($user)) ? 'id' : 'username' ;
$data = $this->_db->get('users', array($field, '=', $user));
if ($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function create($fields = array()) {
if (!$this->_db->insert('users', $fields)) {
throw new Exception("Error Processing Request", 1);
}
}
public function login($username = null, $password = null, $remember = null) {
if (!$username && !$password && $this->exists()) {
Session::put($this->_sessionName, $this->data()->id);
} else {
$user = $this->find($username);
if ($user) {
if ($this->data()->password === Hash::make($password, $this->data()->salt)) {
Session::put($this->_sessionName, $this->data()->id);
if ($remember) {
$hash = Hash::unique();
$hashCheck = $this->_db->get('users_sessions', array('user_id', '=', $this->data()->id));
if (!$hashCheck->count()) {
$this->_db->insert('users_sessions', array(
'user_id' => $this->data()->id,
'hash' => $hash));
} else {
$hash = $hashCheck->first()->hash;
}
Cookie::put($this->_cookieName, $hash, Config::get('remember/cookie_expiry'));
}
return true;
}
}
}
return false;
}
public function update($fields = array(), $id = null) {
if (!$id && $this->isLoggedIn()) {
$id = $this->data()->id;
}
if (!$this->_db->update('users', $id, $fields)) {
Session::flash('uperr', 'We experienced an error while updating your profile');
Redirect::to('account.php');
exit();
}
}
public function hasPermission($key) {
$group = $this->_db->get('groups', array('id', '=', $this->data()->user_group));
if ($group->count()) {
$permissions = json_decode($group->first()->permissions, true);
if ($permissions[$key]) {
return true;
}
}
return false;
}
public function logout() {
$this->_db->delete('users_sessions', array('user_id', '=', $this->data()->id));
Session::delete($this->_sessionName);
Cookie::delete($this->_cookieName);
}
public function data() {
return $this->_data;
}
public function isLoggedIn()
{
return $this->_isLoggedIn;
}
public function exists() {
return (!empty($this->_data)) ? true : false ;
}
}
I'm still following the login/register tutorial I have went over the videos a few times to see if maybe I made a typing mistake somewhere but I can't seem to find anything the error I'm getting is "Notice: Trying to get property of non-object"
I did look around it was suggested to try the below solution however it didn't work:
echo $user[0]->data()->username;
I know it has something to do with my data class, well I think it's my data class that's wrong.
index.php
<?php
require_once 'core/init.php';
if(Session::exists('home')){
echo '<p>' . Session::flash('home', 'You have been registered and can now log in!') . '</p>';
}
$user = new User();
echo $user->data()->username;
?>
Login
User.php
<?php
class User{
private $_db,
$_data,
$_sessionName;
public function __construct($user = null){
$this ->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
if(!$user){
if(Session::exists($this->_sessionName)){
$user = Session::get($this->_sessionName);
if($this->find($user)){
$this->_isLoggedIn = true;
}else{
//logout
}
}
} else{
$this->find($user);
}
}
public function create($fields = array()){
if($this->_db->insert('users', $fields)){
throw new Exception('There was a problem creating account');
}
}
public function find($user = null){
if($user){
$field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username = null, $password = null){
$user = $this->find($username);
if($user){
if($this->data()->password ===Hash::make($password, $this->data()->salt)){
Session::put($this->_sessionName, $this->data()->id);
return true;
}
}
return false;
}
public function data(){
return $this->_data;
}
}
Login.php
<?php
require_once 'core/init.php';
if(Input::exists()){
if(Token::check(Input::get('token'))){
$validate = new Validate();
$validation = $validate->check($_POST, array(
'username' => array('required' => true),
'password' => array('required' => true)
));
if ($validation->passed()){
//log user in
$user = new User();
$login = $user->login(Input::get('username'), Input::get('password'));
if($login){
echo 'Success';
}else{
echo'<p>Sorry invalid details</p>';
}
} else{
foreach($validation->errors() as $error)
echo $error, '<br />';
}
}
}
?>
<form action="" method="POST">
<div class="field">
<label for="username" id="username"> Username </label>
<input type="text" name="username" id="username" autocomplete="off">
</div>
<div class="field">
<label for="password" id="password"> Password </label>
<input type="password" name="password" id="password" autocomplete="off">
</div>
<input type="hidden" name="token" value="<?php echo Token::generate();?>">
<input type="submit" value="Login">
</form>
Home
Session.php
<?php
class Session {
public static function put($name, $value){
return #$_SESSION[$name] = $value;
}
public static function get($name)
{
return self::exists($name) ? #$_SESSION[$name] : null;
}
public static function exists($name)
{
return #$_SESSION[$name] !== null;
}
public static function delete($name){
if(self::exists($name)){
unset($_SESSION[$name]);
}
}
public static function flash($name, $string =''){
if(self::exists($name)){
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
I'm assuming this is the offending code:
$user = new User();
echo $user->data()->username;
This code instantiates a User object, and we can see that the constructor expects the username (or possibly id?) to be given. If no username is given it looks like the find function simply returns false and hence the data array will be empty. This is why you get the error message.
Try calling the constructor with the current username, e.g.
$user = new User('test');
If it's possible for the index page to be loaded without a username, then you just need to add an additional check on the data object before you try to use it, e.g.
if (#$user->data())
echo $user->data()->username;
else
echo "Not logged in";
Basic typing mistake in my init.php file, I really hate myself...
I have been attempting to make a login system with php oop however I have come across this error Warning: Illegal offset type....classes\Session.php on line 11 I'm not quite sure where I'm going wrong any advice would be appreciated.
login
if(Input::exists()){
if(Token::check(Input::get('token'))){
$validate = new Validate();
$validation = $validate->check($_POST, array(
'username' => array('required' => true),
'password' => array('required' => true)
));
if ($validation->passed()){
//log user in
$user = new User();
$login = $user->login(Input::get('username'), Input::get('password'));
if($login){
echo 'Success';
}else{
echo'<p>Sorry invalid details</p>';
}
} else{
foreach($validation->errors() as $error)
echo $error, '<br />';
}
}
}
?>
<form action="" method="POST">
<div class="field">
<label for="username" id="username"> Username </label>
<input type="text" name="username" id="username" autocomplete="off">
</div>
<div class="field">
<label for="password" id="password"> Password </label>
<input type="password" name="password" id="password" autocomplete="off">
</div>
<input type="hidden" name="token" value="<?php echo Token::generate();?>">
<input type="submit" value="Login">
</form>
User
<?php
class User{
private $_db,
$_data,
$_sessionName;
public function __construct($user = null){
$this ->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
}
public function create($fields = array()){
if($this->_db->insert('users', $fields)){
throw new Exception('There was a problem creating account');
}
}
public function find($user = null){
if($user){
$field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username = null, $password = null){
$user = $this->find($username);
if($user){
if($this->data()->password ===Hash::make($password, $this->data()->salt)){
Session::put($this->_sessionName, $this-data()->id);
return true;
}
}
return false;
}
private function data(){
return $this->_data;
}
}
Session
<?php
class Session {
public static function exists($name){
return(isset($_SESSION[$name])) ? true : false;
}
public static function put($name, $value){
return $_SESSION[$name] = $value;
}
public static function get($name){
return $_SESSION[$name];
}
public static function delete($name){
if(self::exists($name)){
unset($_SESSION[$name]);
}
}
public static function flash($name, $string =''){
if(self::exists($name)){
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
index
<?php
require_once 'core/init.php';
if(Session::exists('home')){
echo '<p>' . Session::flash('home', 'You have been registered and can now log in!') . '</p>';
}
echo Session::get(Config::get('session/session_name'));
?>
You should check if session key exist before trying to access it:
<?php
class Session {
public static function put($name, $value){
return $_SESSION[$name] = $value;
}
public static function get($name)
{
return self::exists($name) ? $_SESSION[$name] : null;
}
public static function exists($name)
{
return #$_SESSION[$name] !== null;
}
public static function delete($name){
if(self::exists($name)){
unset($_SESSION[$name]);
}
}
public static function flash($name, $string =''){
if(self::exists($name)){
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
When I login with the correct information I get the following message:
Notice: Undefined property: stdClass::$id in /var/www/classes/User.php on line 37
Success Login!
Line 37 in User.php is following
Session::put($this->_sessionName, $this->data()->id);
Also after i sign in and update page and go to /index.php just to try print out the session, I get nothing.
Following command on index.php page
echo Session::get(Config::get('session/session_name'));
If i don't sign in and just go to index.php i get the following message
Notice: Undefined index: user in /var/www/classes/Session.php on line 12
Login.php
<?php
require_once 'core/init.php';
ini_set('display_errors', 1);
error_reporting(~0);
if(Input::exists()) {
if(Token::check(Input::get('token'))) {
$validate = new Validate();
$validation = $validate->check($_POST, array(
'username' => array('required' => true),
'password' => array('required' => true)
));
if($validation->passed()) {
$user = new User();
$login = $user->login(Input::get('username'), Input::get('password'));
if($login) {
echo 'Success Login!';
} else {
echo 'Login failed';
}
} else {
foreach($validation->errors() as $error) {
echo $error;
}
}
}
}
?>
<form action="" method="post">
<div class="field">
<label for="username">Username</label>
<input type="text" name="username" id="username">
</div>
<div class="field">
<label for="password">Password</label>
<input type="password" name="password" id="password">
</div>
<input type="hidden" name="token" value="<?php echo Token::generate(); ?>">
<input type="submit" value="Logga in">
</form>
Session.php
<?php
class Session {
public static function exists($name) {
return (isset($_SESSION[$name])) ? true : false;
}
public static function put($name, $value) {
return $_SESSION[$name] = $value;
}
public static function get($name) {
return $_SESSION[$name];
}
public static function delete($name) {
if(self::exists($name)) {
unset($_SESSION[$name]);
}
}
public static function flash($name, $string = '') {
if(self::exists($name)) {
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
User.php
<?php
class User {
private $_db,
$_data,
$_sessionName;
public function __construct($user = null) {
$this->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
}
public function create($fields = array()) {
if(!$this->_db->insert('users', $fields)) {
throw new Exception('Could not create account');
}
}
public function find($user = null) {
if($user) {
$field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username = null, $password = null) {
$user = $this->find($username);
if($user) {
if($this->data()->password === Hash::make($password, $this->data()->salt)) {
Session::put($this->_sessionName, $this->data()->id);
return true;
}
}
return false;
}
private function data() {
return $this->_data;
}
}
Token.php
<?php
class Token {
public static function generate() {
return Session::put(Config::get('session/token_name'), sha1(uniqid()));
}
public static function check($token) {
$tokenName = Config::get('session/token_name');
if(Session::exists($tokenName) && $token === Session::get($tokenName)) {
Session::delete($tokenName);
return true;
}
return false;
}
}