i build a website and it has a sign in form, when user sign in, the sign in form will not appear, and a sign out will apprear instead
my problem is when the user sign out the session doesn't destroy
when user sign in , i got to the function run, when user sign out i go to the function sign out
HTML
<?php
Session::init();
$l = Session::get('loggedIn');
if (isset($l) && $l==true) {
?>
sign out
<?php
} else {
?>
Sign in
<br/>
<form action="<?php echo URL;?>login/run" method="POST">
<div class="staticSignin">
phoneNumber
password
</div>
<div id="userInputSignin">
<input type="text" name="MNumber"/>
<input type="password" name="password"/>
<input type="image" src="http://localhost/Mar7ba/public/images/signinButton.png"/>
</div>
</form>
<?php
}
?>
run for sign in
Session::init();
$row = $sth->fetch();
$ID = $row['ID'];
$rollID = $row['rollID'];
Session::set('loggedIn', true);
Session::set('ID', $ID);
Session::set('roolOfUser', $rollID);
sign out
public function signout() {
Session::set("loggedIn", false);
Session::destroy();
$this->view->render('index/index');
}
Session Class
<?php
class Session {
public static function init() {
session_start();
}
public static function set($key, $value) {
#$_SESSION[$key] = $value;
}
public static function get($key) {
if (isset($_SESSION[$key]))
return $_SESSION[$key];
}
public static function destroy() {
unset ($_SESSION);
session_destroy();
}
}
when sign out , the sign in form doesn't appear
To destroy a session you need first to start it using session_start(), seems that you aren't doing this
Try to do it:
session_start();
// Deleting all content in $_SESSION
$_SESSION = array();
// Destroying the session
session_destroy();
EDIT 1
Try to do these changes in destroy() to test if the session is really being started:
public static function destroy() {
session_start();
// Deleting all content in $_SESSION
$_SESSION = array();
// Destroying the session
session_destroy();
}
Related
I have the following code
$user;
if (isset($_POST['submitLogin']))
{
$GLOBALS['user'] = logIn();
// location1
}
function logIn()
{
$user = new User("my username", "my email");
return $user;
}
// location2
Then I want to display that information like this:
echo $GLOBALS['user']->__get('username');
but it only works in location1.
I have worked around this by using a global array and passing the data from the User instance to that global array, but this defeats the purpose of using classes.
If you could just give me a hint or put me on the right track I'd be very thankful.
I don't quite follow what you are asking. But you can always pass objects to functions through arguments, rather than using globals. Demonstration here:
<?php
ini_set('display_errors', true);
error_reporting(E_ALL);
class UserSignup
{
public $username;
public $email;
public function __construct($username, $email)
{
$this->username = $username;
$this->email = $email;
}
}
function process_signup_form()
{
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
$user = new UserSignup(
$_POST['username'] ?? null,
$_POST['email'] ?? null
);
if(signup($user))
echo 'Thanks for signing up!';
}
}
function signup(UserSignup $user)
{
echo 'Signing up:' . $user->username . ' with email:' . $user->email;
return true;
}
process_signup_form();
?>
<form method="post">
<input type="text" name="username">
<input type="email" name="email">
<input type="submit">
</form>
As stated here: https://stackoverflow.com/a/132197/9439763
it's OK [to store an object inside $_SESSION] as long as by the time the session_start() call is made, the class declaration/definition has already been encountered by PHP or can be found by an already-installed autoloader. otherwise it would not be able to deserialize the object from the session store.
This was the problem, I now fixed it by including the class declaration before the session call.
<?php
require_once './model/user.class.php';
session_start();
...
Thank you all, and a special thanks to #Kodos Johnson for showing me the way.
I have a problem with my login the login works it checks the html forms and it the info is correct it will login me to the logged in page.I set the username and user id on the login page after the info is checked but the server seems like it wont save the info. Strange thing is if i logout then use the login the site works registers the username etc on the login i check the info then set the username into a variable then do
if(empty($_SESSION['username']))
{
echo "Somthing went wrong";
echo '<META HTTP-EQUIV="Refresh" Content="0; URL=logout.php">';
}
But this does not trigger again once i go to the site for the first time in a while i need to view the logout page before i can logout even tho im not logged in of course the logout only destroys the session.
if (isset($_POST["Username"]) && !empty($_POST["Username"])) {
$salt= "";
$username23 = mysql_real_escape_string($_POST['Username']);
$thereusername = strip_tags($username23);
$password2= sha1 ($salt.$_POST["password"]);
$statement = $db->prepare("SELECT * FROM users WHERE username = ? AND password = ? ");
$statement->execute(array($thereusername,$password2));
$count = $statement->rowCount();
/// If usernam and password match we carry on
if ($count == "1"){
$username23 = mysql_real_escape_string($_POST['Username']);
$thereusername = strip_tags($username23);
$statement8 = $db->prepare("SELECT * FROM users WHERE username = ? ");
$statement8->execute(array($thereusername));
$count8 = $statement8->fetch();
$username233 = mysql_real_escape_string($count8['id']);
$_SESSION['userid'] = strip_tags($username233);
$_SESSION['username'] = $thereusername ;
if(empty($_SESSION['username'])){
echo "Somthing went wrong";
echo '<META HTTP-EQUIV="Refresh" Content="0; URL=logout.php">';
}
if(empty($_SESSION['userid']))
{
echo "Somthing went wrong";
echo '<META HTTP-EQUIV="Refresh" Content="0; URL=logout.php">';
}
echo "You are now being logged in";
echo '<META HTTP-EQUIV="Refresh" Content="0; URL=dashboard.php">';
exit;
echo "works";
}
};
?>
.
<form action="login.php" method="post">
<div class="row">
<div class="form-group col-sm-6">
<label for="exampleInputEmail1">Username</label>
<input class="form-control" type="text" value="Artisanal kale" name= "Username" id="Username">
</div>
<div class="form-group col-sm-6">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" name= "password" id="password"placeholder="Password">
</div>
</div>
<div class="row">
<div class="col-sm-4">
<p> <input type="submit" value="Submit" class="btn theme-btn"> </p>
</div>
</div>
</form>
I of course use the session start at the top of the page after i login it takes me to the logged in page but will not display the username or any info ive done print_r session and get Array ( ) i then go to logout.php and login and all works perfect server error or php error ?
First off, don't do your own password salt/encrypt, you need to use password_hash() to save password hashes and password_verify() (or bcrypt equivalent) to check the hashed password vs submitted password. Second, as noted, you need to use PDO exclusively. Lastly, you need to make some classes to make your script more manageable and easier to troubleshoot. This is more complex because there are a lot of parts that need to be implemented but this is an basic example of where you should be going with your login and such. I would advise, if you don't understand the majority of this, you probably should download a framework because this type of thing is complex to do it right. Frameworks have this all built in, you just have to program the very top level of the script, for the most part...
/core/classes/App.php
class App
{
# Storage of global arrays
protected static $GlobalArray = array();
# Returns post trimmed POST array
public function getPost($key=false)
{
if(!isset(self::$GlobalArray['_POST']))
self::$GlobalArray['_POST'] = $this->sanitizeArray($_POST);
if(!empty($key))
return (isset(self::$GlobalArray['_POST'][$key]))? self::$GlobalArray['_POST'][$key] : false;
return self::$GlobalArray['_POST'];
}
# Trims the values
public function sanitizeArray($array)
{
if(!is_array($array))
return trim($array);
foreach($array as $key => $value) {
$array[$key] = $this->sanitizeArray($value);
}
return $array;
}
}
/core/classes/User.php
class User extends App
{
private $con;
public function __construct(\PDO $con)
{
$this->con = $con;
}
public function savePassword($username,$password)
{
# Create the password hash
$hash = password_hash($password);
# Prepare the query and store password hash
$query = $this->con->prepare("UPDATE users SET `password` = ? WHERE `username` = ?");
$query->execute(array($username,$password));
return $this;
}
public function validateUser($username,$password)
{
# Prepare the query to get the user
$query = $this->con->prepare("SELECT * FROM users WHERE `username` = ? LIMIT 1");
$query->execute(array($username));
# Assign password
$user = $query->fetch(\PDO::FETCH_ASSOC);
if(empty($user['password']))
return false;
# Match hash to password
if(!password_verify($password,$user['password']))
return false;
# Return the user data
return $user;
}
}
/core/classes/Session.php
class Session extends App
{
public function toSession($array)
{
foreach($array as $key => $value) {
$_SESSION[$key] = $value;
}
}
# Save to errors array
public function toError($array)
{
foreach($array as $key => $value) {
$_SESSION['errors'][$key] = $value;
}
}
# Get error
public function getError($key=false)
{
if(!empty($key))
return (isset($_SESSION['errors'][$key]))? $_SESSION['errors'][$key] : false;
return (isset($_SESSION['error']))? $_SESSION['error'] : false;
}
# Get value
public function get($key=false)
{
if(!empty($key))
return (isset($_SESSION[$key]))? $_SESSION[$key] : false;
return (isset($_SESSION))? $_SESSION : false;
}
public function start()
{
session_start();
}
public function destroy($key=false)
{
if(!empty($key)) {
if(isset($_SESSION[$key])) {
$_SESSION[$key] = null;
unset($_SESSION[$key]);
}
}
else {
session_destroy();
}
}
}
/config.php
# Create important defines
define('DS',DIRECTORY_SEPARATOR);
define('ROOT_DIR',__DIR__);
define('CORE',ROOT_DIR.DS.'core');
define('CLASSES',CORE.DS.'classes');
define('FUNCTIONS',ROOT_DIR.DS.'functions');
# A class autoloader is a must...
spl_autoload_register(function($class){
$path = str_replace(DS.DS,DS,CLASSES.DS.str_replace('\\',DS,$class).'.php');
if(is_file($path))
include_once($path);
});
# Include connection
include(FUNCTIONS.DS.'functions.php');
# Create connection
$db = mysqlconnect();
# Start the session
$Session = new Session();
$Session->start();
/login.php
# Add our config file
require_once(__DIR__.DIRECTORY_SEPARATOR.'config.php');
# Create application
$App = new User($db);
# Check if submission login
if(!empty($App->getPost("Username"))) {
# Get the user array (returns on validated)
$User = $App->validateUser($App->getPost("Username"),$App->getPost("password"));
# If user is valid
if($User){
$Session->toSession(array(
'userid'=>$User['id'],
'username'=>$User['username']
));
# Redirect & stop
header('Location: dashboard.php');
exit;
}
else {
# Store the error
$Session->toError(array("invalid_login"=>"Invalid username or password"));
# Redirect to error or whatever...
}
}
I haven't really checked this, but I have noted so you know what does what (or is supposed to do). You want to always include the config.php at the top of every top level page for consistency.
Use print_r($Session->get()); to see the session array. Also note the password check won't work if you haven't saved the password hash properly.
I've just started learning to do oop and I just wanted to put the most basic set of code together to make sure I'm understanding things correctly. I wanted to capture a form entry in the $_POST variable and pass it to an object to have it output something back to the browser. No SQL, no Security measures, just proof of understanding.
Here is the form:
<html>
<head>
<title>SignUp Form</title>
</head>
<body>
<?php
if(!empty($_POST['name'])) {
include_once "class.php";
} else {
?>
<form method="post" action="signup.php">
<label for="name">Enter name below:</label></br>
<input type="text" name="name" id="name"></br>
<input type="submit" value="Submit">
</form>
<?php
}
echo $name->processName($_POST['name']); ?>
</body>
</html>
And here is the class:
<?php
class Process {
public $entry;
function __construct($entry) {
$this->entry = $entry;
}
public function processName($entry) {
return "You entered " . $this->entry . ".";
}
}
$name = new Process($_POST['name']); ?>
This is working without error right now but it doesn't seem like I should have to enter the $_POST in the echo statement on the form page and in the object on the class page. Is this correct? Should I instead be collecting that in the $entry property. It's working, but I don't think the execution is correct. Thanks in advance!
Your right you don't need to enter the $_POST variable into that function, you could change it to this and it would work without entering the post:
public function processName() {
return "You entered " . $this->entry . ".";
}
Because right now processName function doesn't do anything with the class's public $entry variable, it just echoes out what you put in when you call the function.
What you likely want to do instead is:
Change public $entry; to protected $entry;
Then:
public function getEntry() {
return $this->entry;
}
Then in your html, after constructing the class, you can just put this to get the $entry variable:
echo $name->getEntry();
Coming from Symfony framework background. You could do something right this:
<?php
class Process
{
protected $post_var;
public function __construct($p)
{
$this->post_var = $p;
}
public function getData()
{
//checking if not post request
if(count($this->post_var) == 0) {
return false;
}
$result_arr = [];
//populating $result_arr with $_POST variables
foreach ($this->post_var as $key => $value) {
$result_arr[$key] = $value;
}
return $result_arr;
}
}
$process = new Process($_POST);
$data = $process->getdata();
if($data)
{
echo $data["name"];
}
?>
<form action="" method="post">
<input type="text" name="name"/>
<input type="submit" name="submit"/>
</form>
i bet there are scripts out there already about this, but I'm creating this project just for fun and to test my knowledge, now i just want the public's opinions, and if you guys find a way I could improve feel free to share as well to comment against it.
My question is simply how to create a good salt. after reading the manual, and a few book chapters this is what i came up with. Although i feel like my salt should be longer for security. what should I change?
Here is my user class. please check genSalt() function and guide me to figure out how to improve my results.
<?php
if(!defined('ACCESS_CORE')){
echo 'Permission Not Granted';
exit;
}
class user{
private $_email;
private $_pass;
private $_db;
private $_url;
function __construct(){
$this->_db = $this->db();
$this->_url = 'localhost'; //change this to ur url
if(isset($_POST['user_login'])){
$this->_email = $this->clean($_POST['user_email']); //sanitize later
$this->_pass = $this->clean($_POST['user_password']);
}
}
protected function db(){
$db = parse_ini_file('../contra.conf');
$this->_db = new mysqli($db['host'], $db['user'], $db['pass'], $db['name']);
if ($this->_db->connect_errno) {
trigger_error("Failed to connect to MySQL".$mysqli->connect_errno). $mysqli->connect_error;
}
}
protected function clean($string){
return mysql_real_escape_string($string); #TODO: add more options html etc
}
public function safeReferer(){
$ref = (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''); //if there is a ref..
if(empty($ref) || strpos($ref, $this->_url)){
return true;
} else {
return false;
}
}
public function includeForm($message = ""){ #TODO: finish form view page
?>
<div id="logForm">
<h3>User Authentication Form</h3>
<?php echo ($message === "") ? '' : $message; ?>
<form id="loginForm" method="post" action="login.php">
<input type="text" name="user_email" />
<input type="password" name="user_password" />
<input type="submit" value="Login" name="user_login" />
<a href="/" >Forgot password?</a>
</form>
</div>
<?php ;
}
protected function genSalt($length) { #TODO: improve something is fishy
$prefix = '$2a$'.$length.'$'; //blowfish prefix
//base64 unique random alphanumeric
$uniqRand = base64_encode(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM));
$modified_string = str_replace('+', '.', $uniqRand);
$salt = substr($modified_string, 0, $length);
return $prefix.$salt.'$';
}
protected function correctPass($password, $salt){ #TODO: change to prepared statement. best method?
$sql = "SELECT pass, s FROM users WHERE email = '$this->_email'";
if($result = $this->_db->query($sql)){
while ($row = $result->fetch_object()) {
if(cript($row['pass'], $row['s']) === $row['s']){
return true;
} else {
return false;
}
}
}
}
public function login(){
if($this->correctPass($this->_email, $this->_pass)){
echo 'create session, session cookie, start timeout, and redirect'; #TODO: copy login, finish page on form view
} else {
$message = '<h5>Please try again</h5>';
$message .= '<p>It looks like you have either entered a wrong user name or password.';
$this->includeForm($message);
}
}
// test function, similar function in register class
public function createPass($pass){
$salt = $this->genSalt(10);
$hash = crypt($pass, $salt);
echo $salt. '--';
echo 'hashed pass : '. $hash;
echo '<br> entered pass : '.$pass.'<br>';
if(crypt($pass, $hash) == $hash ){
echo 'true';
} else {
echo 'false';
}
}
}
?>
test function results...
$2a$10$WlUvRqsgZl$--
hashed pass : $2a$10$WlUvRqsgZl$$$$$$$$$$$. tRNdwECDQXhN07g4mIp82xxFCTUev3m
entered pass : mypassword
true
Why not consider the password_hash function? It also hashes but generates a random salt every time and uses blowfish by default. It requires PHP 5.5 or later, however.
After submitting my form below via ajax the message always comes back as failed, even with the correct login information! I've coded this in a non oop style too and it works perfectly, but when i use this style of code it hangs up. The live site is http://andyholmes.me/demo/summersproperty/OOP/login.php and the username is admin#summersproperty.com and password is admin
login.php -
<?PHP
session_start();
include('includes/class.login.php');
$login = new Login();
$token = $_SESSION['token'] = md5(uniqid(mt_rand(), true));
if ($_POST['ajax']) {
exit($login->getStatus());
}
?>
<style>
#message { display: none; cursor: pointer; }
.loader { display: none; }
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#loginForm").submit(function(e) {
$(this).fadeOut(300);
$('.loader').delay(300).fadeIn(100);
$.post("<?=$_SERVER['PHP_SELF'];?>", { username: $('#username').val(), password: $('#password').val(), ajax: true }).done(function(data) {
if (data.logged_in == true) {
// Redirect with javascript
$('.loader').delay(2000).fadeOut(100);
$('#message').html('<p>Success! We\'ll redirect you in a minute...</p>').delay(2200).fadeIn(200);
} else {
$('.loader').delay(2000).fadeOut(100);
$('#message').html('<p>Failed... Click to try again!').delay(2200).fadeIn(200);
$('#message').on('click', function(){
$(this).fadeOut(200);
$('#loginForm').delay(350).fadeIn(200);
});
}
});
return false;
});
});
</script>
<form id="loginForm" method="POST" action="">
<table>
<tr><td>Username:</td><td><input type="text" name="username" id="username"/></td></tr>
<tr><td>Password:</td><td><input type="password" name="password" id="password"/></td></tr>
</table>
<input type="hidden" name="token" value="<?=$token;?>"/>
<input type="submit" name="login" value="Log In"/>
</form>
<div class="loader">
<img src="loader.gif"/>
</div>
<div id="message"></div>
and the login class -
<?PHP
class Login
{
private $_id;
private $_username;
private $_password;
private $_passmd5;
private $_errors;
private $_access;
private $_login;
private $_token;
public function __construct()
{
$this->_errors = array();
$this->_login = isset($_POST['login']) ? 1 : 0;
$this->_access = 0;
$this->_token = $_POST['token'];
$this->_id = 0;
$this->_username = ($this->_login) ? $this->filter($_POST['username']) : $_SESSION['username'];
$this->_password = ($this->_login) ? $this->filter($_POST['password']) : '';
$this->_passmd5 = ($this->_login) ? md5($this->_password) : $_SESSION['password'];
}
public function isLoggedIn()
{
($this->_login) ? $this->verifyPost() : $this->verifySession();
return $this->_access;
}
public function filter($var)
{
return preg_replace('/[^a-zA-Z0-9]/','',$var);
}
public function verifyPost()
{
try
{
if(!$this->isTokenValid())
throw new Exception('Invalid form submission');
if(!$this->isDataValid())
throw new Exception('Invalid form data entered');
if(!$this->verifyDatabase())
throw new Exception('Invalid username/password combination');
$this->_access = 1;
$this->registerSession();
}
catch(Exception $e)
{
$this->_errors[] = $e->getMessage();
}
}
public function verifySession()
{
if($this->sessionExist() && $this->verifyDatabase())
$this->_access = 1;
}
public function verifyDatabase()
{
include('dbConfig.php');
$data = mysql_query("SELECT user_id FROM users WHERE user_username = '{$this->_username}' AND user_password = '{$this->_passmd5}'");
if(mysql_num_rows($data))
{
list($this->_id) = #array_values(mysql_fetch_assoc($data));
return true;
}
else
{
return false;
}
}
public function isDataValid()
{
return (preg_match('/^[a-zA-Z0-9]/', $this->_username) && preg_match('/^[a-zA-Z0-9]/', $this->_password)) ? 1 : 0;
}
public function isTokenValid()
{
return (!isset($_SESSION['token']) || $this->_token != $_SESSION['token']) ? 0 : 1;
}
public function registerSession()
{
$_SESSION['id'] = $this->_id;
$_SESSION['username'] = $this->_username;
$_SESSION['password'] = $this->_passmd5;
}
public function sessionExist()
{
return (isset($_SESSION['username']) && isset($_SESSION['password'])) ? 1 : 0;
}
public function showErrors()
{
echo "<h3>Errors</h3>";
foreach($this->_errors as $key=>$value)
echo $value."<br>";
}
public function getStatus()
{
return json_encode(array('logged_in' => $this->isLoggedIn(), 'errors' => $this->showErrors()));
}
}
?>
By the way, i know i need to use PDOs etc, but i just want to get the script to a point where it works nicely before i change the database connection data. I know im close, but its really frustrating!
If you can help me, i will be most grateful!
EDIT NOTES: This code has been updated for an issue that has come up after using the suggestion from user1781670
<?PHP
session_start();
include('includes/class.login.php');
$login = new Login();
$token = $_SESSION['token'] = md5(uniqid(mt_rand(), true));
if ($_POST['ajax']) {
exit($login->getStatus());
}
?>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#loginForm").submit(function(e) {
$.post("<?=$_SERVER['PHP_SELF'];?>", { username: $('#username').val(), password: $('#password').val(), ajax: true }).done(function(data) {
if (data.logged_in == true) {
// Redirect with javascript
} else {
// Inject errors to html
// data.errors
}
});
return false;
});
});
</script>
<form id="loginForm" method="POST" action="">
<table>
<tr><td>Username:</td><td><input type="text" name="username" id="username"/></td></tr>
<tr><td>Password:</td><td><input type="password" name="password" id="password"/></td></tr>
</table>
<input type="hidden" name="token" value="<?=$token;?>"/>
<input type="submit" name="login" value="Log In"/>
</form>
As you can see I modified your jquery removing you PHP code inside because that's not the place where it goes, also I changed the syntax a little to one more clear at least for me. Also note that "data" is a json returned by your PHP function getStatus who returns the login status as json.
Now you just need to create the PHP function that return the json. Maybe can help you to checkout json_encode. If you get stuck please tell us.
Example of getStatus function:
JavaScript objects are like associate arrays in PHP except JavaScript objects can have functions. So, is not surprise you need to pass an associative array to json_encode.
public function getStatus()
{
return json_encode(array('logged_in' => $this->isLoggedIn(), 'errors' => $this->showErrors()));
}
$.post automatically knows it received a JSON (it's the default option), so you can access it's properties with data.logged_in and data.errors.
This is the problem: you show your login form and when the user submit the form, through ajax you open a connection and send the data entered by the user and you expect the server to return information. But how is that data gonna be returned? how are you gonna handle it? well, that is JSON for. It's a syntax to write JavaScript objects, so with json_encode you return a JSON and when your JavaScript receives that JSON you can access it's data and check if it was a successful login.