Using xampp for local development, I was able to build a very simple authentication for accessing a webpage. Everything worked fine on my local machine but I ran into some issues while testing it on my live server.
Instead of creating the database in phpMyAdmin, I had to use the MySQL Databases tool in my cPanel. No big deal, I guess, just create the myLogin database, then go into phpMyAdmin to add the myUsers table with ID, username, and password, and finally insert the user 'admin' with a hashed password.
Issue 1: I guess it only makes sense, but the following resulted in an error:
$DATABASE_HOST = 'localhost';
$DATABASE_USER = 'root';
$DATABASE_PASS = '';
$DATABASE_NAME = 'myLogin';
Failed to connect to MySQL: Access denied for user 'root'#'localhost' (using password: NO)
So, I opened mySQL Database again and added a user with a password and attached it to the myLogin database. I edited the code in the auth.php file to reflect the changes and... no error! However, no nothing.
Issue 2: After I enter the password and hit enter the browser just goes to the auth.php file and does nothing. No echoes, no redirect upon success, nothing. Below is the entire auth.php file:
<?php
session_start();
$DATABASE_HOST = 'localhost';
$DATABASE_USER = 'myUser';
$DATABASE_PASS = 'myPass';
$DATABASE_NAME = 'myLogin';
$con = mysqli_connect($DATABASE_HOST, $DATABASE_USER, $DATABASE_PASS, $DATABASE_NAME);
if ( mysqli_connect_errno() ) {
die ('Failed to connect to MySQL: ' . mysqli_connect_error());
}
if ( !isset($_POST['uName'], $_POST['pWord']) ) {
die ('Please fill both the username and password field!');
}
if ($stmt = $con->prepare('SELECT id, password FROM myUsers WHERE username = ?')) {
$stmt->bind_param('s', $_POST['uName']);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$stmt->bind_result($id, $password);
$stmt->fetch();
if (password_verify($_POST['pWord'], $password)) {
session_regenerate_id();
$_SESSION['loggedin'] = TRUE;
$_SESSION['name'] = $_POST['uName'];
$_SESSION['id'] = $id;
header('Location: ../wica.php');
} else {
echo 'Incorrect password!';
}
} else {
echo 'Incorrect username!';
}
$stmt->close();
}
?>
As I mentioned, I am a complete PHP newbie, this has all been cobbled together thanks to various tutorials.
I don't know why it won't even echo "Incorrect password!" when I type the wrong password. It just sits on auth.php and does nothing and I'm clueless. This is my first time using mySQL on the remote server. Could there be critical settings that aren't the same as my xampp setup? Did I miss an important step somewhere?
Also, it seems a little insecure to have the DATABASE_USER and DATABASE_PASS just sitting in the auth.php file for anyone to see. Was I not supposed to do this? What are the secure alternatives, or are there any?
In case you got caught in the wheels of the comment-train, here's the answer:
My local dev. server (xampp) is running PHP 7+ while my remote server's PHP version was 5.4x, preventing password_verify from working. I was able to update the remote server's PHP version and everything worked. (Thank you fyrye!)
As was pointed out, the php code itself was a mess, so I found a better tutorial, I hope, and re-wrote the auth file:
<?php
if ( isset($_POST['pWord'])) {
require '../../../dbh.inc.php';
$username = $_POST['uName'];
$userpass = $_POST['pWord'];
if(empty($username) || empty($userpass)) {
header("Location: ../index.html?error=emptyFields");
exit();
}
else {
$sql = "SELECT * FROM users WHERE username=?";
$stmt = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../index.html?error=sqlerror");
exit();
}
else {
mysqli_stmt_bind_param($stmt, "s", $username);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if($row = mysqli_fetch_assoc($result)) {
$pwdCheck = password_verify($userpass, $row['password']);
if($pwdCheck == false) {
header("Location: ../index.html?error=wrongPass");
exit();
}
else if($pwdCheck == true) {
session_start();
$_SESSION['loggedin'] = TRUE;
header("Location: ../wica.php");
exit();
}
else {
header("Location: ../index.html?error=wrongPass");
exit();
}
}
else {
header("Location: ../index.html?error=noUser");
exit();
}
}
}
}
else {
header("Location: ../index.html?error=justWrong");
exit();
}
?>
You might notice that I also moved the database credentials to an include that now resides above the public root.
Is it the best solution? Probably not, but learning how to implement something like DotEnv is beyond me atm. I don't actually know PHP, I just use it sometimes like a pleb. Plus, I just spent a month translating 3000+ lines of Actionscript into javascript and creating html/css equivalents for all the .swf library elements. My brain is currently oatmeal. Hope my follies can at least help someone else.
Related
So here is the deal, I have been following tutorials all day trying to resolve this issue I am having.
So far my webpage shows "Username invalid" , but I have confirmed in the inspector in chrome that it is infact passing the correct username and password to my login script (below) am I doing anything wrong?!
<?php
session_start();
// Change this to your connection info.
$DATABASE_HOST = 'db_ip';
$DATABASE_USER = 'db_user';
$DATABASE_PASS = 'db_pass';
$DATABASE_NAME = 'db_name';
// Try and connect using the info above.
$con = mysqli_connect($DATABASE_HOST, $DATABASE_USER, $DATABASE_PASS, $DATABASE_NAME);
if ( mysqli_connect_errno() ) {
// If there is an error with the connection, stop the script and display the error.
exit('Failed to connect to MySQL: ' . mysqli_connect_error());
}
// Now we check if the data from the login form was submitted, isset() will check if the data exists.
if ( !isset($_POST['username'], $_POST['password']) ) {
// Could not get the data that should have been sent.
exit('Please fill both the username and password fields!');
}
// Prepare our SQL, preparing the SQL statement will prevent SQL injection.
if ($stmt = $con->prepare("SELECT id, password FROM `accounts` WHERE username = '$username'")) {
// Bind parameters (s = string, i = int, b = blob, etc), in our case the username is a string so we use "s"
$stmt->execute();
// Store the result so we can check if the account exists in the database.
$stmt->store_result();
if ($stmt->num_rows > 0) {
$stmt->bind_result($id, $password);
$stmt->fetch();
// Account exists, now we verify the password.
// Note: remember to use password_hash in your registration file to store the hashed passwords.
if ($_POST['password'] === $password) {
// Verification success! User has loggedin!
// Create sessions so we know the user is logged in, they basically act like cookies but remember the data on the server.
session_regenerate_id();
$_SESSION['loggedin'] = TRUE;
$_SESSION['name'] = $_POST['username'];
$_SESSION['id'] = $id;
echo 'Welcome ' . $_SESSION['name'] . '!';
} else {
echo 'Incorrect password!';
}
} else {
echo 'Incorrect username!';
}
$stmt->close();
}
?>
I was able to resolve my issue with the following:
where I was defining $stmt I was using $username when it had not been defined yet, I changed this line
$con->prepare("SELECT id, password FROM `accounts` WHERE username = '$username'"))
to
$con->prepare('SELECT id, password FROM `accounts` WHERE username = ?'))
and added this above my execute statement:
$stmt->bind_result($id, $password);
I have created a website lately with a group of students, but were having some troubles.
We created the website in php 5.4 on a localhost and it worked perfectly.
But now we wanted to get the site online and the webhosting is using a different version of php(5.6).
So now the session does not start.
It redirects us to the homepage, but we are not logged in.
We were thinking that it was because of the version of php, since it did work at first.
<?php
include_once 'connect.php';
session_start();// Starting Session
// Storing Session
$user_check=$_SESSION['gebruiker'];
// SQL Query To Fetch Complete Information Of User
$ses_sql="select email_adres from gebruiker where email_adres='".$user_check".'";
$row = mysqli_fetch_assoc($ses_sql);
$login_session =$row['username'];
if(!isset($login_session)){
header('Location: login.php'); // Redirecting To Home Page
}
else{
header('Location: acountgegevens.php');
}
?>
<?php
include_once 'connect.php';
function logincheck(){
if(isset($_POST['submit'])){
$error = 0;
// declare variables
$email = null;
$password = null;
// check if email address has been set
if (isset($_POST['email_adres']) &&
!empty($_POST['email_adres'])) {
$email = addslashes($_POST['email_adres']);
}
// check if password has been set
if (isset($_POST['password']) && !empty($_POST['password'])) {
$password = md5($_POST['password']);
}
if ($email == null || $password == null) {
$error = 1;
}
// query database for user credentials
$db = new PDO('**');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$statement = $db->prepare("SELECT *
FROM gebruiker
WHERE email_adres = :email
AND wachtwoord = :password
LIMIT 1");
$statement->execute(array(':email' => $email, ':password' => $password));
$result = $statement->fetch(PDO::FETCH_OBJ);
if (!$result) {
$error = 1;
} else {
session_start();
$_SESSION['gebruiker'] = $email;
var_dump($_SESSION);
?>
<script>location.href='index.php'</script>
<?php
}
return $error;
}
}
?>
These two files are included, but we cant figure it out.
Could someone help?
I would hazzard a guess that your connect.php has not been changed to match the hosting companies host/user/password and therefore is outputting an error message.
This of course means that session_start() , which was placed after the connect.php and therefore after your script has attempted to send something to the browser, will not work.
You are only seeing the result of the failed session_start() but I would check the connect.php is configured correctly for its new hosting location
I am new to PHP / MySql programming. I have purchased a book to help learn the language and I have done well so far except when I tried to create an authentication system.
I want to be able to match the record to the database using MD5 encryption and if found send to the website. If the username and password are incorrect then send them to the login page again.
At one point it would only match the first record. Now it won't match any. I can type exactly what is in the database and the result still goes to 0 or back to the login page.
Also I am wanting to set a session variable for the username and auth_level so that I can call on it throughout my website/application.
I am using XAMPP on Mac if that helps.
Auth Script:
if ((!isset($_POST['username'])) || (!isset($_POST['password']))) {
header('Location: login.html');
exit;
}
$mysqli = mysqli_connect('localhost', 'username', 'password', 'testDB')
or die(mysql_error($mysqli));
$username = mysqli_real_escape_string($mysqli, $_POST['username']);
$password = mysqli_real_escape_string($mysqli, $_POST['password']);
$auth_sql ="SELECT username , auth_level FROM auth_users WHERE
username ='".$username."' AND password =MD5('".$password."')";
$auth_sql_res = mysqli_query($mysqli, $auth_sql) or die(mysqli_error($mysqli));
if (mysqli_num_rows($auth_sql_res) == 1) {
$_SESSION['username'] = $username;
header('Location: homebeta.php');
} else {
header("Location:index.php");
exit;
}
PHP v5.3.1
Thank you everyone that takes the time to look, analyze, and/or help. I really appreciate your time.
You forgot an exit after the first call to header:
header('Location: homebeta.php');
exit;
Are you checking PHP errors? Read How to get useful error messages in PHP? to know more.
I think your script may output something at the beginning, that prevents headers or session information to be sent.
Try this:
if ((!isset($_POST['username'])) || (!isset($_POST['password']))) {
header('Location: http://www.replacethis.com/login.html');
} else {
$mysqli = mysqli_connect('localhost', 'username', 'password', 'testDB')
or die(mysql_error($mysqli));
$username = mysqli_real_escape_string($mysqli, $_POST['username']);
$password = mysqli_real_escape_string($mysqli, $_POST['password']);
$auth_sql = "SELECT `username`, `auth_level`
FROM `auth_users`
WHERE `username` = '$username' AND `password` = MD5('$password')";
$auth_sql_res = mysqli_query($mysqli, $auth_sql)
or die(mysqli_error($mysqli));
if (mysqli_num_rows($auth_sql_res) > 0) {
$_SESSION['username'] = $username;
header('Location: http://www.replacethis.com/homebeta.php');
} else {
header("Location: http://www.replacethis.com/index.php");
exit;
}
}
Else statement added.
Backticks in your SQL query (Just to be on the safe side)
Absolute URL in the header location.
And try removing the MD5 hashing from your query and copy n paste both username AND password in your HTML-form and then login.
Well, you may not getting your error messages, since you are using mysql_error instead of mysqli like everything else, and specifically on connect, there is mysqli_connect_error().
Also, according to the manual, inside the parentheses should be void for mysqli_connect_error:
$mysqli = mysqli_connect('localhost', 'username', 'password', 'testDB')
or die(mysqli_connect_error());
I'm creating a login page where the user name and password are entered and then checked against the database to see if they match (I have posted on this previously but my code was completely incorrect so I had to start over) Upon clicking the submit button the user should be directed to the homepage (index.php) if the two values match up or an error message should appear stating "Invalid login. Please try again." Very simple basic stuff. Yet, I cannot get any variation to work.
Here is my code without the validation check. I believe this code is right but, if not, could someone please explain as to why. I am not asking anyone to write any code, just explain why it is not working properly.
<?php
function Password($UserName)
{
//database login
$dsn = 'mysql:host=XXX;dbname=XXX';
$username='*****';
$password='*****';
//variable for errors
$options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
//try to run code
try {
//object to open database
$db = new PDO($dsn,$username,$password, $options);
//check username against password
$SQL = $db->prepare("Select USER_PASSWORD FROM user WHERE USER_NAME = :USER_NAME");
$SQL->bindValue(':USER_NAME', $UserName);
$SQL->execute();
$username = $SQL->fetch();
if($username === false)
{
$Password = null;
}
else
{
$Password = $username['USER_PASSWORD'];
}
return $Password;
$SQL->closeCursor();
$db = null;
} catch(PDOException $e){
$error_message = $e->getMessage();
echo("<p>Database Error: $error_message</p>");
exit();
}
?>
Now the validation code. I've googled this and found several hundred ways to do so but this method most closely matches my coding style. It is incomplete and I would like some help as to how to finish it properly and then where to place it within the code above. My assumption is right after this comment: "//check username against password". Now I've seen this version twice and in one version the check is for txtUserName and the other is just username. I believe there should be else statements after each if statement to direct them to the index.php page. Also, the third if statement is the check to see if the password matches the username. No variation of this did I understand. They were far too complex.
function Login()
{
if(empty($_POST['txtUserName']))
{
$this->HandleError("UserName is empty!");
return false;
}
if(empty($_POST['txtPassword']))
{
$this->HandleError("Password is empty!");
return false;
}
$username = trim($_POST['txtUserName']);
$password = trim($_POST['txtPassword']);
if(!$this->($username,$password))
{
return false;
}
}
I know I am asking a lot here. But I am very new to PHP and am really trying hard to learn it. And there is way too much info out there and most of it is not for beginners. Any, and all, help would be greatly appreciated.
To begin with, let's assume that we have a PDO connection, just like you do already, for example with this function:
You can do something like:
// Usage: $db = connectToDataBase($dbHost, $dbName, $dbUsername, $dbPassword);
// Pre: $dbHost is the database hostname,
// $dbName is the name of the database itself,
// $dbUsername is the username to access the database,
// $dbPassword is the password for the user of the database.
// Post: $db is an PDO connection to the database, based on the input parameters.
function connectToDataBase($dbHost, $dbName, $dbUsername, $dbPassword)
{
try
{
return new PDO("mysql:host=$dbHost;dbname=$dbName;charset=UTF-8", $dbUsername, $dbPassword);
}
catch(Exception $PDOexception)
{
exit("<p>An error ocurred: Can't connect to database. </p><p>More preciesly: ". $PDOexception->getMessage(). "</p>");
}
}
So that you can have a database connection like this:
$host = 'localhost';
$user = 'root';
$dataBaseName = 'databaseName';
$pass = '';
$db = connectToDataBase($host, $databaseName, $user, $pass);
So far we have the same stuff as you.
Now, I assume that we're on a PHP page where the user submitted his username and password, to begin with: check if we really received the username and the password, with the ternary oprator:
// receive parameters to log in with.
$userName = isset($_POST['userName']) ? $_POST['userName'] : false;
$password = isset($_POST['password']) ? $_POST['password'] : false;
Now you can validate if those inputs were actually posted:
// Check if all required parameters are set and make sure
// that a user is not logged in already
if(isset($_SESSION['loggedIn']))
{
// You don't want an already logged in user to try to log in.
$alrLogged = "You're already logged in.";
$_SESSION['warningMessage'] = $alrLogged;
header("Location: ../index.php");
}
else if($userName && $password)
{
// Verify an user by the email address and password
// submitted to this page
verifyUser($userName, $password, $db);
}
else if($userName && (!($password)))
{
$noPass = "You didn't fill out your password.";
$_SESSION['warningMessage'] = $noPass;
header("Location: ../index.php");
}
else if((!$userName) && $password)
{
$noUserName = "You didn't fill out your user name.";
$_SESSION['warningMessage'] = $noUserName;
header("Location: ../index.php");
}
else if((!$userName) && (!($password)))
{
$neither = "You didn't fill out your user name nor did you fill out your password.";
$_SESSION['warningMessage'] = $neither;
header("Location: ../index.php");
}
else
{
$unknownError = "An unknown error occurred.". NL. "Try again or <a href='../sites/contact.php' title='Contact us' target='_blank'>contact us</a>.";
$_SESSION['warningMessage'] = $unknownError;
header("Location: ../index.php");
}
Now, let's assume that everything went well and you already have a database connection stored in the variable $db, then you can work with the function
verifyUser($userName, $password, $db);
Like already mentioned in the first else if statement:
// Usage: verifyUser($userName, $password, $db);
// Pre: $db has already been defined and is a reference
// to a PDO connection.
// $userName is of type string.
// $password is of type string.
// Post: $user exists and has been granted a session that declares
// the fact that he is logged in.
function verifyUser($userName, $password, $db)
{
$userExists = userExists($userName, $db); // Check if user exists with that username.
if(!($user))
{
// User not found.
// Create warning message.
$notFound= "User not found.";
$_SESSION['warningMessage'] = $notFound;
header("Location: ../index.php");
}
else
{
// The user exists, here you can use your smart function which receives
// the hash of the password of the user:
$passwordHash = Password($UserName);
// If you have PHPass, an awesome hashing library for PHP
// http://www.openwall.com/phpass/
// Then you can do this:
$passwordMatch = PHPhassMatch($passwordHash , $password);
// Or you can just create a basic functions which does the same;
// Receive 1 parameter which is a hashed password, one which is not hashed,
// so you hash the second one and check if the hashes match.
if($passwordMatch)
{
// The user exists and he entered the correct password.
$_SESSION['isLoggedIn'] = true;
header("Location: ../index.php");
// Whatever more you want to do.
}
else
{
// Password incorrect.
// Create warning message.
$wrongPass = "Username or password incorrect."; // Don't give to much info.
$_SESSION['warningMessage'] = $wrongPass;
header("Location: ../index.php");
}
}
}
And the function userExists($userName, $db) can be like:
function userExists($userName, $db)
{
$stmt = $db->prepare("SELECT * FROM users WHERE USER_NAME = :USER_NAME;");
$stmt->execute(array(":USER_NAME "=>$userName));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if($result)
{
// User exists.
return true;
}
// User doesn't exist.
return false;
}
Where the function Password is like:
function Password($UserName)
{
$stmt = $db->prepare("Select USER_PASSWORD FROM user WHERE USER_NAME = :USER_NAME;");
$stmt->execute(array(":USER_NAME"=>UserName));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if($result)
{
return $result['USER_PASSWORD'];
}
// No result.
return false;
}
Again, make sure you're not matching plain text passwords, or basic shai1, md5 encryptiones etc. I really recommend that you take a look at PHPass.
I hope I'm making myself clear.
I'm relatively new to php, and I'm trying to write a really simple login script. I've got the basic functionality down, but I can't login to the system. My login script is below, and my registration script is below as well.
checklogin.php
include_once 'inc/db.inc.php';
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string(md5($_POST['password']));
try {
$sql="SELECT id, username, password FROM users WHERE username='$username' and password='$password'";
$result = $pdo->query($sql);
$count=mysql_num_rows($result);
// If result matched $username and $password, table row must be 1 row
if($count == 1){
// Register $username, $password and redirect to file "index.php"
session_register("username");
session_register("password");
header("Location: index.php");
}
else {
header("Location: login.php?invalid=1");
}
}
catch (PDOException $e) {
echo $e;
}
ob_end_flush();
?>
checkreg.php
include_once 'inc/db.inc.php';
//This makes sure they did not leave any fields blank
if (!$_POST['username'] | !$_POST['password'] | !$_POST['passwordconf'] ) {
die('You did not complete all of the required fields');
}
if ($_POST['password'] != $_POST['passwordconf']) {
die('Your passwords did not match. ');
}
$_POST['password'] = md5($_POST['password']);
if (!get_magic_quotes_gpc()) {
$_POST['password'] = addslashes($_POST['password']);
$_POST['username'] = addslashes($_POST['username']);
}
$username = $_POST['username'];
$password = $_POST['password'];
try {
// now we insert it into the database
$sql = "INSERT INTO users(username,password) VALUES ('$username','$password')";
$result = $pdo->exec($sql);
header("Location: index.php");
} catch (PDOException $e){
echo $e;
}
?>
I know that the registration is writing to the database, but everytime I attempt a valid login I receive my invalid credentials flag. Anything you can do to help me would be awesome. Thank you.
Your issue could be with session_register(), depending on the version of PHP you're using. Try putting
session_start();
At the top of checklogin.php, then using
...
$_SESSION['username'] = $username;
$_SESSION['password'] = $password;
...
instead of session_register().
First you should clear some things out:
1.
if (!$_POST['username'] | !$_POST['password'] | !$_POST['passwordconf'] ) {
die('You did not complete all of the required fields');}
it should be && and not |.
In your code there's nowhere to check if username exists or not, so i'm guessing that you have multiple users with the same username. Before inserting in your checkreg.php, you should fist check if the username exists or not.
in your checklogin.php change if($count == 1) to if($count > 0)
If this not helped could you give me more information like database data (the data that is in your database now)
<?php
// Use of session_register() is deprecated
$barney = "A big purple dinosaur.";
session_register("barney");
// Use of $_SESSION is preferred, as of PHP 4.1.0
$_SESSION["zim"] = "An invader from another planet.";
// The old way was to use $HTTP_SESSION_VARS
$HTTP_SESSION_VARS["spongebob"] = "He's got square pants.";
?>
Warning:
This function has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
Couple of things to try:
1) The session_register function call is deprecated. http://php.net/manual/en/function.session-register.php. You really ought to be using $_SESSION if at possible.
Something like this:
$_SESSION["username"] = $username;
$_SESSION["password"] = "validated"; // md5 is variable so you can't easily check for it on next page render
2) When testing for the values, you don't want $_POST, you want to use $_SESSION again on the next page render. Something like this:
if ("validated" == $_SESSION["password"]) {
// You're logged in...
}
3) Note, for the $_SESSION array to be populated you must call session_start(); once and only once before use. (http://www.php.net/manual/en/function.session-start.php for more.)
4) I know this is sample code, but SQL Injection attack possible. Need to escape those variables.
$sql="SELECT id, username, password FROM users WHERE username='$username' and password='$password'";