I have a pretty simple function, it checks to see if ['id'] exists in the session and redirects if that's the case, located on the top of my login.php
It works, but only after I submit the login form twice.
require_once 'inc/header.inc';
which contains before html:
<?php
require 'inc/init.php';
session_regenerate_id();
?>
init.php contains
<?php
session_start();
if(!isset($_SESSION) || empty($_SESION) ){
require 'inc/db.php';
require 'users.class.php';
require 'general.class.php';
require 'functions.php';
$users = new Users($db);
$general = new General($db);
$errors = array();
}
?>
This is the top of my login.php :
<?php
require_once 'inc/header.inc';
if ($general->is_logged_in()) {
header("Location: index.php");
exit;
}
Yet the page keeps on loadin the first time.
The function if you care for it:
public function is_logged_in() {
if (isset($_SESSION['id'])) {
return true;
} else {
return false;
}
}
don't you think it should be like this
session_start();
session_regenerate_id();
as in your function the id is generated first and then session is started as a result of which the values is not assigned to session.
Just added redirect after return/setid from login(), rather than relying on checking if id exists at page load and runnin the redirect on page load - user can then not re-enter the page in any case. Not sure why the former wouldn't work.
Related
I tried to write my own authentication method (school project), and I'm stuck.
Please advise, how to solve a secure authentication:
There is an index.php which contains everything that needs to be "protected". I will copy the relevant parts of my code here.
updated index.php
session_start();
function checkUserAuth(){
$authStatus = false;
if (isset($_SESSION['PHPSESSID'])){
if ($_SESSION['PHPSESSID'] == $_COOKIE['PHPSESSID']){
$authStatus = true;
}
}
return $authStatus;
}
if(!checkUserAuth()){
include_once(dirname(__DIR__).'/admin/authentication/login.php');
exit();
}
If the checkUserAuth() determines, that there is no properly authenticated user, will include the login.php and stop the rest of the script.
updated login.php:
if(array_key_exists($username, $users) && password_verify($password, $users[$username])){
$_SESSION['PHPSESSID'] = $_COOKIE['PHPSESSID'];
$_SESSION['login_user'] = $_POST['user'];
What I imagine that might happen, is that if the login details are correct, the login.php sets a cookie, and refreshes the page. Then the index.php will detect the cookie, and skip the login part.
The login is pretty much figured out, and thanks to Juned, I think it is working now. However I don't know how secure is this?
On a scale from 1 to very, how wrong I am?
There are loads of ways of doing this. The below pseudocode is not the most efficient but should work and I don't think what you've done above will actually work.
Does this help?
login.php pseudocode
<?php
session_start(); // this function checks if there's a session ID already set, if not, sets one.
if(array_key_exists($username, $users) && password_verify($password, $users[$username])){
// do your login details checking here
// if login details correct
// set a flag in the $_SESSION superglobal and whatever else you want to store about the user like their username e.g.
$_SESSION["loggedIn"] = true;
$_SESSION["username"] = "$_POST['user']"; // better practice to fetch a clean version from your database
//else return user to login page
}
?>
index.php pseudocode
<?php
session_start(); // this will fetch the session ID and other variables that you might have set e.g. username, logged in status
function checkUserAuth(){
$authStatus = false;
if (isset($_SESSION['loggedIn']) && $_SESSION['loggedIn'] === true){
$authStatus = true;
}
return $authStatus;
}
if(!checkUserAuth()){
// redirect to login page. e.g.
header('Location: login.php');
exit;
}
?>
I have been developing the following php script (+ sqlite database) to create a login for my web.
Up to now I had used just one PHP file, but now I want to use different files for login and protected contents, I mean, I used to have all my web in one file php (contents and password script were together) but now I want to detach it in different php files (one for the login, login.php, and other phps protected: index.php, calendar.php...)
I used this code to password-protect php content:
<?php require_once "Login.php"; ?>
but it doesn't seem to work: it displays the form to login next to the content I wanted to protect.
This is the php script I'm using as login.php:
<?php
$db = new PDO('sqlite:data.db');
session_start();
if (isset($_GET['logout'])) {
unset($_SESSION['pass']);
header('location: index.php');
exit();
}
if (isset($_SESSION['timeout'])) {
if ($_SESSION['timeout'] + 4 < time()) {
session_destroy();
}
}
if (!empty($_POST['pass'])) {
$result = $db->query("SELECT user,password FROM users");
foreach ($result as $row) {
if (password_verify($_POST['pass'], $row['password'])) {
echo "Welcome! You're logged in " . $row['user'] . "! <a href='index.php?logout=true'>logout</a>";
$_SESSION['pass'] = $_POST['pass'];
$_SESSION['timeout'] = time();
}
}
}
if (empty($_SESSION['pass'])) {
echo '<form method="POST" action=""><input type="password" name="pass"><form>';
}
?>
MY QUESTION IS: How can I use my php script to protect different files?Is there any way to embed a logout link too?
One way is to store a token in session variables when a user logs in. Confirm the token is there on each page, if it isn't redirect the user to the login page. For example assert_login.php:
<?php
session_start();
if('' == $_SESSION['token']) {
header("Location: login.php");
exit();
}
?>
Then, in the PHP at the top of each of your pages:
<?php
require('assert_login.php');
?>
You can also clear the session variable on logout, logout.php for example:
<?php
require('assert_login.php'); // has session_start() already
$_SESSION['token'] = ''; // empty the token
unset($_SESSION['token']); // belt and suspenders
header("Location: login.php");
exit();
?>
I was also going through same issue & the way I solved it:
PSEUDO CODE:
PHP SESSION START
if(isset(GET(logout){
SetLogout();
die()}
$redirect=false
if not session[auth] exists
if SERVER REQUEST METHOD IS POST
$redirect=true;
if POST(username) && POST(pass) exists
Sanitize both of them & assign to $user& $pass
if user == "John" && $pass == "secret"
Go To SetLogin();
else{
Go To SetLogout();
echo "Wrong Username or Password"
drawlogin();
die();}
} //user pass comparing ends
} //Server method is NOT POST, so maybe it is GET.
//Do nothing, let the control pass to next lines.
}//SESSION(auth) does not exists, so ask user to login
else {
drawlogin();
}
//Post-Redirect-Get
if ($redirect)
redirect header to this same page, with 301
die()
// Secret Content here.
function SetLogin($user){
$SESSION(auth) = TRUE;}
function SetLogout($user){
if SESSION(auth) exists
unset($SESSION(auth))
redirect back with 301, without query string //shake ?logout
}
function drawlogin(){
echo all the HTML for Login Form
What it does is, it checks various things/variables, and if all passes, the control passes to Secret Content.
Save it as pw.php, & include it on top of any file you want to protect. Logout can be triggered by Logout
Note that this is just a pseudo code, typed on a tablet. I will try to update it with actual version. It is not checked for errors. Use all standard PHP Security precautions..
I have tried passing sensitive information from 1 page to the next using Cookies and PHP Sessions but still no luck. This works fine in all browsers I have tested except Opera Mini. I also found this: http://caniuse.com/#search=cookie
This is how I have it currently setup.
page1.php:
<?php
session_start();
$time = time();
$key = '';
$hash = md5($key . $time);
$_SESSION['inno'] = '';
header("Location: page2.php". $hash);
exit;
?>
page2.php:
<?php
session_start();
if (isset( $_SESSION['inno'])) {
include("../global/header.php");
include("../global/content.php");
}
session_destroy();
?>
The content of the page is the sensitive information, So that is why it goes from page1.php to page2.php.
Is there some kind of workaround for this if passing information this way isn't supported in Opera Mini?
Use classes for reusable resources, they are less messy.
Looks like you forgot to assign data, so
Here is the promising structure:
index.php
<?php
include_once 'session.php';
$my_session = new session_helper;
//SET YOUR SESSION VARIABLES
if($my_session->get_session_data('username') == null){
$sessionData = array(
'username'=>'me',
'logged'=>true,
'password'=>md5('password')
);
$my_session->set_session_data($sessionData);
}
?>
View my session
view_session.php
<?php
include_once 'session.php';
$my_session = new session_helper;
?>
<!--GET YOUR SESSION VARIABLES-->
<p>Username: <?php echo $my_session->get_session_data('username'); ?></p>
<p>Logged: <?php echo $my_session->get_session_data('logged'); ?></p>
<p>Password: <?php echo $my_session->get_session_data('password'); ?></p>
<p> </p>
<?php $my_session->debug_session(); ?>
session.php to get rid of headaches
<?php
//MANAGE YOUR SESSION
class session_helper
{
//Start session when class instance created
function __construct()
{
session_start();
}
//Session data set using an array to easily add multiple values e.g. on login page
function set_session_data($sessionData)
{
forEach($sessionData as $key => $value){//Go through each key
$_SESSION[$key] = $value;//And assign it to session
}
}
function get_session_data($session_data_key)
{
return $_SESSION[$session_data_key];//Call this to get your values
}
function debug_session()
{
print_r($_SESSION); //Check what session contains if something is wrong
}
function close_session()
{
session_destroy(); //Good to use for fresh start/logout.
}
}
?>
session.php manages sessions. Accessing directly will output an empty page.
index.php uses a condition to set the variables. You don't need to rework data everytime when you have it.
view_session.php has all the info regarding the session.
Best practice of retrieving info is storing secure/encrypted primary keys of the database, then use them to retrieve everything else from the database, e.g. by user ID get the e-mail, profile creation time, name, surname etc.
I have multiple pages on my site, most of which are member only pages which a user should have access to only once logged in.
When a user lands at my page they automatically land on the index/home page (index.php). If a user tried to navigate to dashboard.php which is for members only, then they should be redirected back to index.php so they can log in.
at the top of all of my member pages like dashboard.php and manage_account.php i am including a header.php file like so:
include 'header.php';
once a user is logged in i create the session '$_session['user']'
And i am using the following header redirect to check if the session exists and if it doesn't then redirect that user.
<?php
session_start();
include 'config.php';
if (empty($_SESSION['user'])) {
header('Location: index.php');
exit;
}
?>
My problem is rather than cut and paste a header redirect code to each and every member page I just want to place it in the header.php page as this is being included in all of my member pages including my home page index.php.
however it creates a continuous redirect and does not load the page, it says the web
Probably because the header is included as well in the index, right? You can check for that on the condition before redirecting:
<?php
session_start();
include 'config.php';
if (empty($_SESSION['user']) && parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) != '/index.php') {
header('Location: index.php');
exit;
}
?>
You could set an array in your config.php with which pages need be validate and then compare with current page to define if will validate.
For example:
$member_pages = array('dashboard', 'member-page', 'etc');
$current = $_SERVER['REQUEST_URI'];
if (empty($_SESSION['user']) && array_search($current, $member_pages) !== FALSE) {
header('Location: index.php');
exit;
}
Hope it helps!
Within member pages do:
$memberOnly = true;
include 'header.php';
and in header.php:
if (isset($memberOnly)) {
if (empty($_SESSION['user'])) {
header('Location: index.php');
exit;
}
}
In public pages (non-member available) you simply:
include 'header.php'
without worrying about $memberOnly
If i understand your problem correctly, your header.php file is included in every page. Though this header.php file contains code which is executed:
header.php:
<?php
// This code is executed whenever you include this file
session_start();
include 'config.php';
if (empty($_SESSION['user'])) {
header('Location: index.php');
exit;
}
?>
You get a redirection loop, what means that this code is also executed in the index.php page. Maybe the header.php file is included in the index.php file as well.
If you would extract the code to a function and call it only in the pages which require a logged in user, you would avoid this loop.
header.php:
<?php
// The code in this function is not called automatically when the file is included
function redirectToLoginIfNecessary()
{
if (!isset($_SESSION['user'])) {
header('Location: index.php');
exit;
}
}
?>
index.php:
<?php
session_start();
include 'header.php';
// Public accessible pages do not call the function
...
?>
secret.php:
<?php
session_start();
include 'header.php';
// Protected pages do call the function
redirectToLoginIfNecessary();
...
?>
This works for me.
Using header is best, but has to be used before any other content is sent to the browser. Which, for me, developing in schmurdpress, makes it hard to implement.
if ( is_user_logged_in() ) {
echo 'Cool!';
} else {
$url = "https://yourdomain.com/log-in/";
echo '<META HTTP-EQUIV="refresh" content="0;URL=' . $url . '">';
}
You redirect index.php to index.php - if the access file is index.php your redirection shouldn't be fired.
<?php
session_start();
include 'config.php';
$basename = substr(strtolower(basename($_SERVER['PHP_SELF'])),0,strlen(basename($_SERVER['PHP_SELF']))-4);
if ((empty($_SESSION['user'])) && ($basename!="index")) {
header('Location: index.php');
exit;
}
?>
Add this check just before the redirect
if ($_SERVER["PHP_SELF" ] != "index.php")
I've been having a really rough time trying to implement a logon system for my web application.
I have the basic logic working as far as my index.php goes - if users try to navigate there and are not logged in it redirects them to the logon screen. Once they've provided correct credentials they are directed properly back to the protected index.php page.
This logic in code is seen here:
(index.php)
<?php
session_start();
include_once 'db_functions.php';
require_once 'access.php';
if (!userIsLoggedIn()) {
include 'login.php';
exit();
}
The problem occurs when a user attempts to navigate to another protected page. My logic was for protected pages to check whether the user was logged in, and if not send them back to the index which would in turn send them to a logon screen.
(protectedpage.php)
<?php
session_start();
require_once 'access.php';
echo "Logged in: " + $_SESSION['loggedIn'];
echo "User: " + $_SESSION['email'];
echo "Password: " + $_SESSION['password'];
// receive data from HTML readcalllog request
$rName=$_POST["registration"]; //irrelevant post data
$rowId=$_POST["rowid"]; //irrelevant post data
if ($_SESSION['loggedIn'] == FALSE) {
header('Location: http://www.myapp.com/index.php'); //if not logged in, return to index.php, which in turn redirects to a logon page.
exit();
}
As you can see I included test echo statements to print out the details of the current session. When I would navigate to the page (turning off the redirect feature) to check the error messages it would print "000", without the "Logged in: " or "User: " text in front of it.
I performed a test and printed out the details successfully on the index.php page, so for some reason the session is being lost as I navigate from index.php to another protected page.
Any help would be greatly appreciated!
EDIT:
Here is a portion of the userIsLoggedIn() in access.php function which sets the session variables:
function userIsLoggedIn()
{
if (databaseContainsAuthor($_POST['email'], $password))
{
session_start();
$_SESSION['loggedIn'] = TRUE;
$_SESSION['email'] = $_POST['email'];
$_SESSION['password'] = $password;
return TRUE;
}
else
{
session_start();
unset($_SESSION['loggedIn']);
unset($_SESSION['email']);
unset($_SESSION['password']);
$GLOBALS['loginError'] =
'The specified email address or password was incorrect.';
return FALSE;
}
}
}
EDIT 2:
If I login to the index page, go to the protected page(which sends me to a logon screen) and login again, the sessions function properly and all protected pages are accessible.
I just need to figure out what's preventing the initial logon from creating a proper session that carries over.
First of all, you do not need to include session_start(); more then once in a page. Just insert it at the beginning of each file.
If I were you, I would use this statement to see if the user is logged in or not in the protected pages:
if ( !isset($_SESSION['email'] && !isset($_SESSION['password'] ) ) {
header('Location: http://www.myapp.com/index.php'); //if not logged in, return to index.php, which in turn redirects to a logon page.
exit();
} else {
echo "Logged in";
}
Also, I would recommend you using both $_SESSION and $_COOKIES to create a stronger log in system.