I am using this code to create a secure log in page in PHP. I got it from http://girlswhogeek.com/tutorials/2006/creating-a-secure-php-login-page.
<?php
$username = "user";
$password = "pass";
$randomword = "bibblebobblechocolatemousse";
if (isset($_COOKIE['MyLoginPage'])) {
if ($_COOKIE['MyLoginPage'] == md5($password.$randomword)) {
?>
CONTENT HERE
<?php
exit;
} else {
echo "<p>Bad cookie. Clear please clear them out and try to login again.</p>";
exit;
}
}
if (isset($_GET['p']) && $_GET['p'] == "login") {
if ($_POST['name'] != $username) {
echo "<p>Sorry, that username does not match. Use your browser back button to go back and try again.</p>";
exit;
} else if ($_POST['pass'] != $password) {
echo "<p>Sorry, that password does not match. Use your browser back button to go back and try again.</p>";
exit;
} else if ($_POST['name'] == $username && $_POST['pass'] == $password) {
setcookie('MyLoginPage', md5($_POST['pass'].$randomword));
header("Location: $_SERVER[PHP_SELF]");
} else {
echo "<p>Sorry, you could not be logged in at this time. Refresh the page and try again.</p>";
}
}
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>?p=login" method="post">
<fieldset>
<label>
<input type="text" name="name" id="name" /> Name
</label>
<br />
<label>
<input type="password" name="pass" id="pass" /> Password
</label>
<br />
<input type="submit" id="submit" value="Login" />
</fieldset>
</form>
It works really well, however, when there is a mistake in the log in information, it switched to a blank page and echos out a message saying the log in information is wrong. I was wondering if there were a way to have it echo to a div on the page with the inputs. I tried putting the relevant echo messages inside a div but it didn't work. I must admit that I don't even know why it's going to a blank page.
Also, is this the best way to do it or is there a way to make it more secure?
Thanks for any rendered assistance.
Benny.
There are 2 issues:
The exit in your code stop the execution of the page so after 'echo-ing' your message, the page stops
If you want to display in a div, set the message in a variable and display it in the div code
Here is an example of your code, re-worked a bit (you might want to adjust):
<?php
$message = NULL;
if (isset($_COOKIE['MyLoginPage'])) {
if ($_COOKIE['MyLoginPage'] == md5($password . $randomword)) {
?>
CONTENT HERE
<?php
exit;
} else {
$message = "<p>Bad cookie. Clear please clear them out and try to login again.</p>";
}
}
if (isset($_GET['p']) && $_GET['p'] == "login") {
if ($_POST['name'] != $username) {
$message = "<p>Sorry, that username does not match. Use your browser back button to go back and try again.</p>";
} else if ($_POST['pass'] != $password) {
$message = "<p>Sorry, that password does not match. Use your browser back button to go back and try again.</p>";
} else if ($_POST['name'] == $username && $_POST['pass'] == $password) {
setcookie('MyLoginPage', md5($_POST['pass'] . $randomword));
header("Location: $_SERVER[PHP_SELF]");
} else {
$message = "<p>Sorry, you could not be logged in at this time. Refresh the page and try again.</p>";
}
}
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>?p=login" method="post">
<fieldset>
<label><input type="text" name="name" id="name" /> Name</label>
<br />
<label><input type="password" name="pass" id="pass" /> Password</label>
<br />
<input type="submit" id="submit" value="Login" />
</fieldset>
<?php
if (isset($message)) {
echo "<div>" . $message . "</div>";
}
?>
</form>
Are you putting your entire content, including the <html> tags where it says CONTENT HERE?
The only thing that should go there is the secure content, not the whole page. Your boilerplate html, <html><head><title>title</title></head><body> ... </body></html> should go around the whole block of code you posted. The contents of CONTENT HERE only display with a successful login, so anything that isn't secure shouldn't be shown there.
Here's an alternative implementation of a PHP page locker I wrote a long time ago, that may make this more clear.</shameless plug>
You're echoing the result of the login if it fails, but not displaying a page with it. If you want to display the login failed page within your sites design already, I'd recommend sending them back to the login page with the error message. For example:
header("Location: http://website.com/loginpage.php?failed=1");
and then in the login page's code:
if ($_GET['failed'] == '1') echo "Failed to login. Please try again.";
This way if the login fails, they will be sent back to the login page with the error message.
Related
I have two pages. Index.php and my Login.php.
I am using dropdown menu form for logging in - when the user presses 'Sign in', the data gets sent to the Login.php. It's all okay when the password/username was correct (they get sent to the dashboard).
But how could I display an error right there, in the form? Currently when the username/password is wrong it sends you to a new blank page. I want the error to appear right there on the form.
My form:
<div class="form-group">
<label class="sr-only" for="username">Username</label>
<input type="text" class="form-control" name="user_name" placeholder="Username" required>
</div>
<div class="form-group">
<label class="sr-only" for="password">Password</label>
<input type="password" class="form-control" name="user_password" placeholder="Password" required>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Remember me
</label>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success btn-block">Sign in</button>
</div>
My login.php:
error_reporting(E_ALL);
session_start();
$con = mysqli_connect("localhost", "root", "", "battlesql");
if (!$con) {
echo "<div>";
echo "Failed to connect to MySQL: ".mysqli_connect_error();
echo "</div>";
} else {
if (isset($_POST['user_name']) && isset($_POST['user_password'])) {
$username = stripslashes($username);
$username = mysqli_real_escape_string($con, $_POST['user_name']);
$pass = stripslashes($pass);
$pass = mysqli_real_escape_string($con, $_POST['user_password']);
$pass_hashed = hash('whirlpool', $pass);
$select_user = "SELECT * from accounts where name='$username' AND password='$pass_hashed' LIMIT 1";
$query = mysqli_query($con, $select_user);
$row = mysqli_num_rows($query);
if (!$row) {
echo "<div>";
echo "No existing user or wrong password.";
echo "</div>";
} else {
echo "<div>";
echo "You have been logged in.";
echo "</div>";
}
} else {
echo "MySQL error!";
}
}
In your login.php, instead of echoing "No existing user or wrong password", use this:
if(!$row)
{
die(header("location:index.php?loginFailed=true&reason=password"));
}
And in your index.php, you can generate the message as:
<button type="submit" class="btn btn-success btn-block">Sign in</button>
<?php $reasons = array("password" => "Wrong Username or Password", "blank" => "You have left one or more fields blank."); if ($_GET["loginFailed"]) echo $reasons[$_GET["reason"]]; ?>
There are dozens of ways to do this, but I'll provide you with one.
Looking at your PHP code, I'm not exactly sure where your redirect to the "dashboard" is, but say you have some code like this:
<?php
//Fetch stuff from the database
if($fetchedUsername == $username and $fetchedPassword == $password)
{
header("Location:/dashboard");
return;
}
?>
Then, to send them back to the login form, you would just put something in the else statement:
<?php
if(........)
{
//Redirect to dashboard
}
else
{
header("Location:/login");
return;
}
?>
This will send them back to the form. Now you want to show an error, so one way to do this is to set a GET variable, so in the else statement, change the header to:
header("Location:/login/?error=1");
This will let you check for the error code on the login page.
So onto your login page code. You can use isset() and inline-PHP echoes to print out an error directly into the form. Something like this:
<form>
//Form stuff
<?php if(isset($_GET["error"])):?>
<div class="error">Invalid Username or Password</div>
<?php endif; ?>
</form>
That way you can style div.error without worrying about an empty wrapper showing up when $_GET["error"] is not set.
You can also make the code to echo a bit shorter using inline PHP:
<?=(isset($_GET["error"])) ? "Invalid Username or Password" : ""?>
You can achieve what you want using ajax(asynchronous JavaScript and XML). Send login data to login.php from index.php using an ajax call. Read the reply the ajax call returns and show error/success message.
You can use the jquery $.ajax({}); function to implement this model. If you are having trouble in implementing the $.ajax() function then you can read all about it here.
Also, if you haven't already done it, I suggest you to encrypt the password before sending it login.php.
here is my login page:login.php
<?php
require_once('connectvars.php');
//start the session
session_start();
//clear the error message
$error_msg="";
//If the user isn't logged in ,log them in
if(!isset($_SESSION['user_id']))
{
if(isset($_POST['submit']))
{
//connect to database
$dbc=mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
$user_username=mysqli_real_escape_string($dbc,trim($_POST['username']));
$user_password=mysqli_real_escape_string($dbc,trim($_POST['password']));
if(!empty($user_username)&&!empty($user_password))
{ $query="select user_id,username from gyan_userdata where username='$user_username'and password=SHA('$user_password')";
$data=mysqli_query($dbc,$query);
if(mysqli_num_rows($data)==1)
{
$row=mysqli_fetch_array($data);
$_SESSION['user_id']=$_row['user_id'];
$_SESSION['username']=$_row['username'];
setcookie('user_id',$_row['user_id'],time()+(60*60*24*30));
setcookie('username',$_row['username'],time()+(60*60*24*30));
$home_url='http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/index2.php';
header('Location:'.$home_url);
}
else
{
$error_msg ='<p>Your username or password combination is incorrect</p>';
}
}
else
{
$error_msg= 'You must enter a username and password to log in';
}
}
}
$page_title='Log In';
require_once('header.php');
if(empty($_session['user_id']))
{
echo '<p class="error">'.$error_msg.'</p>';
?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<label for="username">Username:</label>
<input type="text" id="username" name="username" /><br/>
<label for="password">Password:</label>
<input type="password" id="password" name="password" /><br/>
<input type="submit" value="Log in" name="submit" />
</form>
<?php
}
else {
// Confirm the successful log-in
echo '<p class="login">You are logged in as ' . $_SESSION['username'] . '.</p>';
}
?>
I want to make my index.php accessible only after login
I have added this code to my index.php page
here is my index page:index.php
<?php
session_start();
if(!isset($_SESSION['user_id']))
{
echo '<p>Please Login to continue Log In</p>';
exit();
}
?>
<html>
<head>
<link rel="stylesheet" type="text/css" href="index_style.css" />
</head>
<script src="dropdown.js">
</script>
</head>
</html>
but even after logging in I'm again asked to log in.
I think your issue is that you're not setting $_SESSION['user_id'] properly
$row=mysqli_fetch_array($data);
$_SESSION['user_id']=$_row['user_id'];
Should be
$row=mysqli_fetch_array($data);
$_SESSION['user_id']=$row['user_id'];
Note that $_row became $row
Firstly, $_session that's a superglobal. It must be in uppercase.
http://php.net/manual/en/language.variables.superglobals.php
Then, you're using $_row but fetching the array using $row=mysqli_fetch_array($data);
so that will fail.
Use $_row=mysqli_fetch_array($data); if you want to keep what you've already coded.
Add error reporting to the top of your file(s) which will help find errors.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// rest of your code
and or die(mysqli_error($dbc)) to mysqli_query() which would have caught the syntax error.
Sidenote: Error reporting should only be done in staging, and never production.
Here is my form that is using login.php to check if the user is registered, etc.
<form action="login.php" method="post" target="SHOW">
<ul id="login">
<li>
Username:<br />
<input type="text" name="username">
</li>
<li>
Password:<br />
<input type="password" name="password">
</li>
<li>
Submit:
<br />
<input type="submit" name="log in">
</li>
<li>
Register</li>
</ul>
</form>
<iframe id="iframe" name="SHOW" scrolling="no"></iframe>
My dilemma stems with the iframe tags I'm using to display the error messages. If the user is registered I would like to redirect him back to index.php as you can see at the end of the PHP ---> header('Location: index.php');
Problem is that iframe doesn't allow for redirecting. So, I would like to change the target from ---> target="SHOW" to target="_top" or something like that. So, the user is redirected after successfully logging in without using any JavaScript.
My failed attempt at accomplishing this --> $href->removeAttribute('target');
$href->setAttribute("target", "_top");
Here is login.php.
<?php
include 'core/init.php';
if(empty($_POST) === false){
$username = $_POST['username'];
$password = $_POST['password'];
if(empty($username) || empty($password) === true){
$errors[] = 'You need to enter a username and password';
} else if (user_exists($username) === false){
$errors[] = 'We can\'t find that username. Have you registered?';
} else if (user_active($username) === false){
$errors[] = 'You haven\'t activated your account!';
} else {
$login = login($username, $password);
if($login === false){
$errors[] = 'That username/password combination is incorrect';
} else {
$_SESSION['user_id'] = $login;
$href->removeAttribute('target');
$href->setAttribute("target", "_top");
header('Location: index.php');
exit();
}
}
print_r($errors);
}
?>
Since you're POST-ing to the iframe, any action taken by the response will only be valid for the context of the iframe itself, which means that doing a regular HTTP redirection will only change the content of the iframe.
If you want to keep the iframe (which I'd advice against, and instead keep both the error handling and logging in the same controller / file that displays the form), you can redirect by using javascript in your iframe response:
<script type="text/javascript">
parent.location.href = 'http://www.bbc.co.uk/';
</script>
Not pretty, but it works.
i've a problem with php session handling that i can't explain to myself.
I'm studying php from scratch, and i can't figure out how to mantain a session live:
This is my index page, where a user can login or register to the database visiting the right page, and then come back to see if he's logged in:
Code:
Index
<?php session_start(); ?>
Register
Login
<?php
if(isset($_SESSION['login']))
{
echo "Logged as: ".$_SESSION['nlogin'];
?>
<form method="post" action="<?php unset($_SESSION['login']) ?>">
<input type="button" name="logOut" value="LogOut" />
</form>
<?php
}
else
{
echo "Please Register or Login";
}
?>
In fact this work, because when i come back from login.php it says, "Logged as: Admin"
But when i click on the link to get the login page, or register page again from the index page, i should get the same message, "Logged as...", but the session appear to be closed instead. :(
here's login.php:
<?php
session_start();
include "dbConnect.php";
if(isset($_SESSION['login']))
{
echo "Logged as: ".$_SESSION['nlogin']; // IT NEVER SHOW THIS MESSAGE
}
if(isset($_POST['submit']) &&(trim($_POST['submit']) == "Login"))
{
if(!isset($_POST['user']) || $_POST['user']=="")
{
echo "Attenzione inserire l'username.";
}
elseif(!isset($_POST['pwd'])||$_POST['pwd']=="")
{
echo "Attenzione inserire la password.";
}
else
{
$u = trim(filter_var($_POST['user'], FILTER_SANITIZE_STRING));
$u = str_replace(" ","_",$u);
$p = trim(filter_var($_POST['pwd'], FILTER_SANITIZE_STRING));
$p = sha1($p);
$istance = new dbHandle;
$istance->connect();
$data = $istance->query("SELECT * FROM login WHERE username_login = '$u' AND password_login = '$p'");
if(mysql_num_rows($data) == 0)
{
echo "Failed";
echo "<a href='index.php' target='_self'> Go Back </a>";
}
else
{
echo "Logged";
$res = $istance->getdata($data);
$_SESSION['login'] = $res->id_login;
$_SESSION['nlogin'] = $res->username_login;
echo "<a href='index.php' target='_self'> Go Back </a>";
}
}
}
else
{
?>
Login
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
...
<input name="user" type="text" size="20" required="required"/>
...
<input name="pwd" type="password" size="20" required="required"/>
...
<input type="submit" name="submit" value="Login"/>
</form>
<form method="post" action="<?php unset($_SESSION['login']) ?>">
<input type="button" name="logOut" value="LogOut" />
</form>
<?php
}
$istance->disconnect();
?>
When i come back using the link above "Go Back" to the index page, it shows Logged as...
but when i come back here again, it does not.
So i assume my session were destroyed automatically? but why?
Thanks, i appreciate your help.
I forget to say that PHP.ini has
session.cookie_lifetime
set to "0"
Thanks
You are calling unset($_SESSION['login']) many times. It removes your login:
<form method="post" action="<?php unset($_SESSION['login']) ?>">
Try this:
<form method="post" action="index.php">
<input type="button" name="logOut" value="LogOut" />
</form>
<? if (isset($_REQUEST['logOut'])){ session_destroy(); } ?>
unset the session like below
if(isset($_REQUEST['logOut']))
{
unset($_SESSION['login']);
}
You check for if(isset($_SESSION['login'])).
If that results in true, you do <form method="post" action="<?php unset($_SESSION['login']) ?>">
Note the unset($_SESSION['login']) part - after that, if(isset($_SESSION['login'])) will return false.
Session overview :
<?php
// Always Start our session
session_start();
$_SESSION['username'] = 'Saurabh Singh';
$username = $_SESSION['username'];
echo $username;
if(isset($_SESSION['username']))
{
Do your action
}
else
{
echo "Please Register or Login";
}
I don't think the session has been destroyed!
I would start by first removing all the empty lines between the opening tags for php and the
session_start().
Test it again and you could add the line
error_reporting(E_ALL);
below the session_start to see if any error messages are echo(ed) back to you.
In your PHP.ini what
session.cookie_lifetime = 0
means is that the session remain active so long as the browser stays open. It's only destroyed when the browser is closed.
I hope this helps
The following PHP code echoes error before entering mistaken password and gives - Notice: Undefined index: password
<?php
//Specify password here
$pass='pass';
if($_POST['password']!=$pass)
{
echo ("<div class='errmg'>Error</div>");
}
else
{
header( 'Location: admin.php' ) ;
}
?>
Below I've the following HTML
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
Enter password:
<input name="password" type="password">
<input name="send" type="submit" value="Log in!">
</form>
Please help me to repair these errors and make this login-redirect better
If you haven't submitted the form, $_POST is empty, so there's no $_POST['password'], just as the error says. Always check whether variables that may or may not be set exist before using them:
if (isset($_POST['password'])) {
if ($_POST['password'] == $pass) {
header(…);
} else {
// error
}
}
It means that $_POST['password'] isn't properly set. I'm not sure why, it looks find in your code. I would just see if it is set first and then see if it is correct.
if(isset($_POST['password']) {
if($_POST['password'] != $pass) {
echo "<div class='errmg'>Error</div>";
} else {
header('Location: admin.php');
}
}
Secondly, you should always close your html tags, both your input tags arent closed, to close them, add a "/>" at the end instead of just ">" like so:
<input name="password" type="password" />
<input name="send" type="submit" value="Log in!" />