In the application I'm developing I'm having a bug where I direct my browser to my app's index.php, and is then properly redirected to login.php if there is no current session. My problem is that after I type in my correct details on login.php and click submit, I am linked to another login.php screen (instead of returning to index.php with an active session) and required to put in my details again. The first screen has the same CSS formatting as index.php, while the second screen doesn't.
After entering my details on the second screen and clicking login, the sessions seem to function normally. Also, many times I will be presented with one logon screen, ill login and the user's correct Home screen data will be displayed (which requires successful queries from the login data), but if I navigate away from index.php to another screen that requires an active session, it will present the unformatted login.php screen.
If I logout, navigate to a different non-restricted page, and attempt to log back in again within the same browser session, the logon functions correctly with only one screen.
Here are snippets from the relevant files:
index.php
<?php
include_once 'db_functions.php';
require_once 'access.php';
if (isset($_POST['action'])) {
if (userIsLoggedIn()) {
header('Location: http://www.myapp.com/index.php'); //prevents users from having to confirm form resubmission if they refresh the page
}
}
if (!userIsLoggedIn()) {
include 'login.php';
exit();
}
login.php:
login.php
<body>
<h1>Log In</h1>
<?php
if (isset($loginError)) {
echo $loginError;
}
?>
<form action="" method="post">
<div>
<label for="email">Email: <input type="text" name="email" id="email" /> </label>
</div>
<div>
<label for="password">Password: <input type="password" name="password" id="password" /></label>
</div>
<div>
<input type="hidden" name="action" value="login" />
<input type="submit" value="Log in" />
</div>
</form>
</body>
access.php:
<?php
function userIsLoggedIn() {
if (isset($_POST['action']) and $_POST['action'] == 'login') {
if (!isset($_POST['action']) or $_POST['email'] == '' or
!isset($_POST['password']) or $_POST['password'] == '') {
$GLOBALS['loginError'] = 'Please fill in both fields';
return FALSE;
}
$email = $_POST['email'];
$password = $_POST['password'];
if (databaseContainsAuthor($email, $password)) {
session_start(); //LINE 17
$_SESSION['loggedIn'] = TRUE;
$_SESSION['email'] = $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;
}
}
if (isset($_POST['action']) and $_POST['action'] == 'logout') {
session_start();
unset($_SESSION['loggedIn']);
unset($_SESSION['email']);
unset($_SESSION['password']);
header('Location: ' . $_POST['goto']);
exit();
}
session_start();
if (isset($_SESSION['loggedIn'])) {
return databaseContainsAuthor($_SESSION['email'], $_SESSION['password']);
}
}
function databaseContainsAuthor($email, $password) {
include_once './db_functions.php';
$db = new DB_Functions();
$result = $db->accountExists($email, $password);
return $result;
}
?>
Any help would be greatly appreciated!
UPDATE:
Error logs are showing multiple occurances of this error:
PHP Notice: A session had already been started - ignoring session_start() in /home3/monitot5/public_html/app/access.php on line 17
Access.php line 17:
if (databaseContainsAuthor($email, $password)) {
session_start(); //LINE 17
$_SESSION['loggedIn'] = TRUE;
What you should do is to use
session_start();
at the beginning of access.php file and don't use this function any more.
You should also completely change login of your access.php file. The first thing you should always do in this file is checking if there's a valid session for this user. Now you check it at the end of file and probably earlier you clear it because you unset session if there are no $_POST data.
In addition you shouldn't also use password in your session. It's rather very insecure. You should simple store login for your system when user filled in form valid username/email and password and unset it if user has logged out.
Sorry, but I won't write the whole code for you. You should simple look at some examples of code in Google to check how to handle user login/logout in PHP.
Related
I am trying to create a home page. Once the user comes to the site and inputs username and password the data will get posted to a checklogin.php file where it will verify the data the user entered. Is there a way that after it checks the data and it is all good then it redirects the user to another page that is the home page? I want to do this so that my entire checklogin script is not on the home page. then also if the user is in a different part of the site, and they click home, the check login script will run again and it will fail. I understand i can use session variables to see if they have already logged in and then somehow bypass the checklogin script on the home page if they have already logged in, but is this the correct way to do this?
<?php
include'vive_fns.php';
$v_username = trim($_POST['viveuser']);
$v_password = trim($_POST['vivepass']);
if(!isset($_POST['viveuser'])|| empty($v_username)){
echo"Please enter a username"; //should change to redirect
die();
}
elseif(!isset ($v_username) || empty($v_username)) {
echo "Please enter a password"; //should change to redirect
die();
}
//if all data is entered we want to check the password
$mysqli = connect_db();
//set database query
$sql1 = "SELECT password FROM vive_user WHERE username = "."'$v_username'";
//check to make sure a result is returned
if(!$result1 = $mysqli->query($sql1)){
echo 'Could not query database. Please try again later.';//should change to redirect
die();
}
else {
$data = $result1->fetch_array(MYSQLI_NUM);
$db_pass = $data[0];
}
if($db_pass !== $v_password){
$title = 'Incorrect Login Info';
//do_html_header($title); this sets the page title
echo"Incorrect Password";//should change to redirect
die();
}
//if everything checks out need to establish user info
$title = 'Home';
do_html_header($title);
//echo"Logged In";
session_start();
$_SESSION['valid_user']=$v_username;
// at this point i want to redirect
header("Location: home.php");
exit();
check this out i think it would help you to under stand the logic here is first login page where user can put login info
<form action="reg_auth.php" method="post" accept-charset="utf-8">
<div id="inrlog" style="display:none;">
<div class="form-group required">
<label for="UserFirstname">Email</label>
<input name="firstname" class="form-control" maxlength="255" type="text" id="UserFirstname" required="required"/>
</div>
<div class="form-group required">
<label for="UserLastname">Password</label>
<input name="lastname" class="form-control" maxlength="255" type="password" id="UserLastname" required="required"/>
</div>
</div>
</div>
<div class="modal-footer">
<p style="text-align:left;"></p><div class="submit"><input class="btn btn-primary" title="Login" name="login" type="submit" value="Login"/></div><div style="display:none;"></div></form>
here is authenticate page code where user info get authenticate
<?php
if($_POST['login']){
$email = $_POST['email'];
$pwd = $_POST['pwd'];
$m = mysql_fetch_assoc(mysql_query("select * from `register` where `email`='$email' and `pwd`='$pwd'"));
if(!empty($m['email'])){
if($m['status'] == 1){
$_SESSION['login'] = $m['id'];
$_SESSION['displayaname'] = $m['fname'].' '.$m['lname'];
header("Location: myaccount.php");
}else{
header("Location: reg_auth.php?msg=4");
}
exit();
}else{
unset($_SESSION['login']);
unset($_SESSION['displayaname']);
header("Location: reg_auth.php?msg=3");
exit();
}
}
if($_GET['msg'] == 2){
$msg = "Email Already Exists! Please Try Some Different Email.";
}
if($_GET['msg'] == 3){
$msg = "Invalid Username or Password! Please Try Again.";
}
?>
header("Location:http://localhost/form2.php");
exit();
Just change the url as you want.
Yes,
You need to use Session to store the information related to user once the user is successfully authenticated with the username and password field.
once the user is authenticated you can redirect to successful page, i mean allow them to access pages.
if user is not authenticated redirect them to login page again.
if session is expire redirect them to login page again.
Thanks
Amit
Yes this sounds correct.
So you'll have a script on your homepage with login&passw, posting infos to your checklogin.php.
There, you check if datas are correct, if they are correct you use sessions to set him as logged in.
After, you redirect him on to homepage with header() function.
Note that header() function will not work if set after html content but in your case, no html in checklogin.php right ? ;)
I am trying to make a very simple website, where you can go to the main page and log in, of which the code is here example.org/login/index.php:
<?php
session_start();
$warning = $_GET['warning'];
$nolog = $_GET['nolog'];
$username = "Welcome, please log in";
if ($warning) {
$username = "Wrong Username/Password Combination";
}
if ($nolog) {
$username = "Page inaccessible: Login required";
}
if ($logout) {
$username = "Thank you for your session";
}
?>
<!DOCTYPE html>
<body>
<div class="center">
<span class="warning"><?= $username ?></span>
<form action="submit.php" method="post">
<span class="formField">Username:</span><br>
<input type="text" name="user" class="field">
<br>
<span class="formField">Password:</span><br>
<input type="password" name="password" class="field">
<br>
<br>
<input type="submit" name="submit" value="Submit" class="field">
</form>
</div>
</body>
</html>
The submit page looks like this (when I get this to work I won't have the username and password hard coded like this, it's just to be concise for now) example.org/login/submit.php:
<?php
session_start();
$username = $_POST['user'];
$password = $_POST['password'];
if ($username == "admin" && $password == "12345") {
$_SESSION['loggedin'] = TRUE;
header("Location: http://www.example.org/welcome/");
die();
}
else {
$_SESSION['loggedin'] = FALSE;
header("Location: http://www.example.org/login/index.php?warning=true");
die();
}
?>
And the welcome page looks like this example.org/welcome/index.php:
<?php
session_start();
if(!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] == FALSE){
unset($_SESSION);
session_destroy();
header("Location: http://www.example.org/login/index.php?nolog=true");
}
?>
<!DOCTYPE html>
<body>
Hi
</body>
</html>
I know this is a lot of code, but when I try running it the first time around the welcome page returns an error saying that it is inaccessible, and sends me back to the login page, but the second time around it seems to work fine and logs me in. Can anyone understand why that would be?
EDIT:
After looking more into it, I discovered that the problem ONLY exists in Google Chrome and Firefox, but does not exist in other browsers such as Internet Explorer or Apple Safari. This now goes into the rendering engine of the browsers. Does anyone perhaps know of another way that I can use session ID's that might bypass this whole issue on all browsers, perhaps another way of validating a user?
Try to use the following
define('BASE_URL', 'http://www.example.org/');
if ($username == "admin" && $password == "12345") {
$_SESSION['loggedin'] = TRUE;
header("Location:".BASE_URL."welcome.php");
exit();
} else {
header("Location:".BASE_URL."index.php");
exit();
}
Add the following in the begining of welcome page
session_start();
if(!isset($_SESSION['loggedin'])){
header("Location:".BASE_URL."index.php");
exit();
}
If you pay attention to the names of the files that I mentioned, I was saying that I was directing my browser to example.org/login/submit.php and then forwarding that to www.example.org/welcome/index.php.
In Google Chrome and Mozilla Firefox, they care about the difference between having a www before the website or not, whereas in Internet Explorer and Safari they do not care about the difference. On my server the website www.example.org and example.org are mirrors of each other (this is a separate security issue) and therefore Google Chrome and Mozilla Firefox will treat them differently and give them different $_SERVER global variables, whereas Internet Explorer and Safari don't care about that difference.
I'm currently in the process of developing a simple CMS for ONE user (this is unlikely to ever change). Therefore I'm storing login details in a .ini file (when live, will be stored outside root). Then using sessions to detect if the correct user has logged in, and if not, redirect them back to the login page using Header('Location: login.php') I'm curious as to how secure this actually is? Below is a draft of what I've got so far
Login Page:
<?php
session_start();
if ($_GET) {
header("Location: login.php");
die();
}
if (isset($_SESSION['user'])) {
header('Location: admin/index.php');
}
$config = parse_ini_file("login.ini", true);
$user = htmlentities($_POST['user']);
$password = htmlentities($_POST['pass']);
if ($user == $config['login']['user'] && $password == $config['login']['password']) {
$_SESSION['user'] = $_POST['user'];
header('Location: admin/index.php');
}
?>
<form action="login.php" method="POST">
<h2>Username:</h2>
<input type="text" name="user" />
<h2>Password:</h2>
<input type="password" name="pass" />
<input type="submit" Value="Login" />
</form>
Then there would be a check on every page in the admin area for the session, if not redirect to the login using the header location, like so:
Admin Welcome Page
<?php
session_start();
if (!isset($_SESSION['user'])) {
header('Location: ../login.php');
die();
}
And a logout page, would destroy the session.
I understand this is fairly simple and doesn't use a database. But are there any major secruity flaws to this design, using header location a lot, and storing sensitive date in the .ini file. Or for a simple application, is this well suited / not outdated?
My code has two forms that create a text field for both username and password. The php script takes the form information and sends it to the server for it to decide if the strings from the form data correspond with the username and password I want. I also have a logout button form that goes to a logout.php script which logs the user out. If I click the logout button it sends the user to my login.php script and ends the session. I can't get users to login to the website and I cant get users to go to the login.php page if I go to the site that has the logout.php. Here is my code:
Login php Code:
<?php
session_start();
if($_SESSION['login'] == true)
{
header("Location:index.php");
}
else
{
if($_POST['username'] == 'username')
{
if($_POST['pass'] == 'password')
{
$_SESSION['login'] = true;
header('Location:index.php');
}
}
}
?>
Login Form:
<form action="login.php" method="post">
Username: <input type="text" name="username" /> </br>
Password: <input type="password" name="pass" />
<input type="submit" value="submit"/>
</form>
Logout PHP code:
<?php
session_start();
session_destroy();
header('Location:index.php');
?>
index php code:
<?php
session_start();
if($_SESSION['login'] =! true || $_SESSION['login'] == "")
{
header('Location:login.php');
}
?>
index form code:
<form action="logout.php" method="post">
<input type="submit" name="logout" value="logout" />
</form>
The PHP code is listed above the html code before anything is displayed thus why some form actions call back the page again. Thank you
Your main problem is the incorrect operator =! in index.php -- the correct use is != for "does not equal". See more: http://php.net/manual/en/language.operators.comparison.php
You can clean up your login.php file a bit:
login.php
session_start();
$redirect = false;
if($_SESSION['login'] == true) {
$redirect = true;
} elseif (
isset($_POST['username']) &&
$_POST['username'] == 'username' &&
$_POST['pass'] == 'password'
){
$_SESSION['login'] = true;
$redirect = true;
}
if ($redirect) {
header("location:http://www.mydomain.com/index.php");
die();
}
Your login form is fine, except where you use : for properties. All HTML element properties are name="value" -- note the equal sign. So your form:
<form action="login.php" method="post">
You have it correct in your logout form.
One of your goals is to reduce the amount of code you use. So if you're going to do the same thing many times, you should try to isolate that piece of code as a class, a function, or simply in another file that you include. To that end, you could put your check for login in a separate file:
security.php
session_start();
if(!isset($_SESSION['login']) || $_SESSION['login'] !== true) {
header('location:http://www.mydomain.com/login.php');
die();
}
... then use require_once to pull that in on any page where you require the user to be logged in:
index.php
require_once('security.php');
// the rest of your index.php code here
Documentation
PHP comparison operators: http://php.net/manual/en/language.operators.comparison.php
require_once - http://php.net/manual/en/function.require-once.php
Some basic tips for code reuse - http://www.techrepublic.com/article/10-tips-for-php-scripts-reuse-code-with-the-include-and-require-functions/5077715
Your Form fields for the login form are bad.
it should read:
<form action="login.php" method="post">
Username: <input type="text" name="username" /> </br>
Password: <input type="password" name="pass" />
<input type="submit" value="submit"/>
</form>
also i think your boolean condition
if($_SESSION['login'] =! true || $_SESSION['login'] == "")
should be
if($_SESSION['login'] != true || $_SESSION['login'] == "")
Try that, if it doesn't work we'll have another look.
Let's try this again :)
Edit: The die() (or exit()) are needed, otherwise PHP keeps processing.
login.php
if (empty($_SESSION['login']))
{
// checking if username is transmitted and matching (same for password)
if ( ( !empty($_POST['username']) && $_POST['username'] === 'username')
&& ( !empty($_POST['password']) && $_POST['password'] === 'password')
)
{
$_SESSION['login'] = TRUE;
header('Location:index.php');
die();
}
}
else
{
// if this matches, we are already loggged in.
header('Location:index.php');
die();
}
header('Location:login.php');
die();
logout.php
// check if Session exists, otherwise there is nothing to destroy
if (!empty($_SESSION))
{
unset($_SESSION);
}
header('Location:login.php');
die();
index.php
session_start();
// if session doesn't exist we redirect to login
if(empty($_SESSION['login']))
{
header('Location:login.php');
}
As far as I can see, your "Login Form" is incorrect, you need to use '=' instead of ':'.
(Edit: What's with minus rating?)
Also, AFAIR Location must be like Location: http://www.example.com/index.php
I am using PHP to build a very basic login script. However, the else from the ifelse statement shows by default before the user has even clicked log in.
Before the user has even tried to login they are greeted with this:
Warning: Cannot modify header information - headers already sent by (output started at /home/madhous3/public_html/dev/admin/index.php:12) in /home/madhous3/public_html/dev/admin/login.php on line 13
Sorry, please try again.
How do I stop this? However, if the user enters the details correctly, they are directed to the right page.
Code
index.php
<?php
include("login.php");
?>
<h1>Admin Area Login</h1>
<form method="post" action="login.php">
Username<input type="text" name="username" />
Password<input type="text" name="password" />
<input type="submit" name="log_in" value="Log In" />
</form>
login.php
<?php
$username_inputted = $_POST['username'];
$password_inputted = $_POST['password'];
if($username_inputted == 'admin' && $password_inputted == 'password'){
header("location:login_success.php");
}else{
header("location:index.php");
echo "Sorry, please try again.";
}
?>
Try removing the include("login.php") from index.php.
Instead, you should redirect back to index.php from your login.php with a flag specifying that the user entered the wrong information (if they failed the login).
index.php
<?php
if(isset($_REQUEST['fail'])) {
echo 'Login failed.';
}
?>
<h1>Admin Area Login</h1>
<form method="post" action="login.php">
Username<input type="text" name="username" />
Password<input type="text" name="password" />
<input type="submit" name="log_in" value="Log In" />
</form>
login.php
<?php
$username_inputted = $_POST['username'];
$password_inputted = $_POST['password'];
if($username_inputted == 'admin' && $password_inputted == 'password'){
header("location:login_success.php");
} else {
header("location:index.php?fail=1");
}
?>
OK, so what's happening is that in index.php you're including login.php at the start. At that time it imports everything from login.php. Since you're including it, the script is going to run.
At the load of the page index.php, the script on login.php starts. It defines those variables $username_inputted & $password_inputted as null, since the POST hasn't happened yet. Then the if block checks, finds null variables, then the else block fires since the variables aren't equal to the expected login info because they're null.
Therefore the echo fires and is displayed on the screen before anything is POSTed.
Nav_nav's solution should work well, since the only time the 'bad login' echo will be displayed is if someone entered something into the input fields, I just wanted to give you a rundown of the algorithm's reason for messing up.
try this
if (!empty($_POST['username']) && !empty($_POST['password'])) {
//define input vars
$username_inputted = $_POST['username'];
$password_inputted = $_POST['password'];
if($username_inputted == 'admin' && $password_inputted == 'password'){
header("location:login_success.php");
}else{
header("location:index.php");
echo "Sorry, please try again.";
}
}
First get rid of the header('location:login.php'). You can't send a header if you've already started sending any HTML to the browser. And if it did work, you'd get an endless loop of reloads.
Then:
You could check for $_POST ['submit'] and if it doesnt exist then don't show them the try again message.