Jump to content

Login and password hash


LeonLatex

Recommended Posts

I was setting up a login system that was working till I want it to hash the password. I paste both my user table in the database and login.php. I can't find what's wrong, can you?

 

<?php
// Inkluder databasekobling og nødvendige funksjoner
include_once $_SERVER['DOCUMENT_ROOT'] . '/includes/db.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Håndter innloggingsskjemaet som er sendt inn.
    $email = $_POST['email'];
    $password = $_POST['password'];

    // Hent brukerens hashed passord fra databasen basert på e-postadressen
    $sql = "SELECT * FROM users WHERE email = :email";
    $stmt = $pdo->prepare($sql);
    $stmt->bindParam(':email', $email);
    $stmt->execute();
    $user = $stmt->fetch();

    if ($user && password_verify($password, $user['password_hash'])) {
        // Passordet er gyldig, opprett en brukersesjon
        session_start();
        $_SESSION['user_id'] = $user['user_id'];
        $_SESSION['user_role'] = $user['role'];

        // Gi tilbakemelding til brukeren om vellykket innlogging
        header('Location: dashboard.php'); // Omdiriger til en beskyttet side
        exit();
    } else {
        // Feil passord, gi tilbakemelding om innloggingsfeil
        $error_message = "Feil e-postadresse eller passord.";
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <!-- ... Legg til nødvendige meta-informasjon og stiler ... -->
</head>
<body>
    <h2>Logg inn</h2>
    <?php if (isset($error_message)): ?>
        <p><?php echo $error_message; ?></p>
    <?php endif; ?>
    <form method="post" action="login.php">
        <label for="email">E-postadresse:</label>
        <input type="email" id="email" name="email" required>

        <label for="password">Passord:</label>
        <input type="password" id="password" name="password" required>

        <input type="submit" value="Logg inn">
    </form>
</body>
</html>


 

/*
 Navicat MySQL Data Transfer

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users`  (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `middle_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `last_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `city` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `postal_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `birthday` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `country` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `county` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `municipality` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `sex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `display_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `password_hash` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `confirm_password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `confirm_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `role` enum('user','moderator','administrator') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'user',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of users
-- ----------------------------


SET FOREIGN_KEY_CHECKS = 1;

 

Link to comment
Share on other sites

Of course Requinix. Here is that part:

<?php
// Inkluder skriptet for databasekobling.
include_once $_SERVER['DOCUMENT_ROOT'] . '/includes/db.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Hent brukerregistreringsdata fra skjemaet.
    $first_name = $_POST['first_name'];
    $last_name = $_POST['last_name'];
    $email = $_POST['email'];
    $password = $_POST['password']; // Dette skal være passordet i klartekst som brukeren oppgir.

    // Hash brukerens passord før det lagres i databasen.
    $hashed_password = password_hash($password, PASSWORD_DEFAULT);

    // SQL-spørring for å sette inn brukeren i databasen.
    $sql = "INSERT INTO users (first_name, last_name, email, password_hash) VALUES (:first_name, :last_name, :email, :password_hash)";

    // Forbered og utfør SQL-setningen.
    $stmt = $pdo->prepare($sql);
    $stmt->bindParam(':first_name', $first_name);
    $stmt->bindParam(':last_name', $last_name);
    $stmt->bindParam(':email', $email);
    $stmt->bindParam(':password_hash', $hashed_password);
    
    if ($stmt->execute()) {
        // Brukerregistrering vellykket.
        echo "Bruker registrert vellykket!";
        // Du kan omdirigere brukeren til en påloggingsside eller vise en suksessmelding.
    } else {
        // Brukerregistrering mislyktes.
        echo "Brukerregistrering mislyktes. Prøv igjen senere.";
    }
}
?>




 

Link to comment
Share on other sites

Sorry again. There's a little busy here today (every day). The problem is that i get the $error_message = "Feil e-postadresse eller passord.";
...and I dont know why. It has been running fine on another site, but not on this site I am dealing with now. The only difference is the database. I cant find any there. Can you ?

Link to comment
Share on other sites

One of the first things I did was go through the password and username.
I checked the db-connection with this one too:

<?php
$servername = "***.****.********.no";
$username = "*****_*****";
$password = "************";
$database = "*****_*****";

try {
    $pdo = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    echo "Connection successful!";
} catch(PDOException $e) {
    echo "Error connecting: " . $e->getMessage();
}
?>

 

Then I checked if the hashed password was corect and matched. 
As a precaution, I set up a new hashed password string using this code, and paste it into the database table users:

<?php 
$password = '******'; // Replace this with the actual password
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
echo $hashed_password; // This will output the hashed version of the password 
?>

 

Edited by LeonLatex
Link to comment
Share on other sites

I don't think you need password_verify() at all here. 

When saving the password, hash the entered, plaintext, password and store the hashed value. 
When logging in, hash the entered, plaintext, password and compare that to what's in the database table. 

 

Saving password (as you currently have): 

$hashed_password = password_hash($password, PASSWORD_DEFAULT);
. . . 
$sql = "INSERT INTO users (first_name, last_name, email, password_hash) VALUES (:first_name, :last_name, :email, :password_hash)";
. . . 
$stmt->bindParam(':password_hash', $hashed_password);

 

Logging in: 

$email = $_POST['email'];
$password = $_POST['password'];
$hashed_password = password_hash( $password, PASSWORD_DEFAULT );

$sql = "SELECT a, b, c FROM users WHERE email = :email and password_hash = :hashed_password";
. . . 
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':email', $email);
$stmt->bindParam(':hashed_password', $hashed_password );
$stmt->execute();
$user = $stmt->fetch();

If you get no rows back, either the username or entered password is wrong. 

 

Regards, 
   Phill W.

 

Link to comment
Share on other sites

@Phi11W, password_hash() produces a different hash for the same input, every time it is called, because it generates a random salt each time it is called. this is precisely why password_verify() must be used. it takes the algorithm, cost and salt from the existing hashed value, hashes the submitted password using these values, then compares the resulting hash of the submitted value with the existing hashed value.

Link to comment
Share on other sites

@LeonLatex, because you haven't posted the registration and login forms (you could have a typo between the field names and the php code), aren't trimming and validating the inputs before using them (any of the inputs could be empty or contain additional characters due to typo mistakes or something javascript is adding) , and have lumped together the test for the user row and password_verfy() (you currently have no single place to test if a user row was not found, then if the password_hash() didn't match), no one here can determine why this isn't working. you could also be overwriting the $password variable if your actual code is requiring the database connection code right before executing the query.

edit: here's another couple of problems with the form processing code you have posted. you should only store the user_id in a session variable, then query on each page request to get any other user data, such as permissions/roles, so that any change in these other values will take effect on the very next page request after they have been changed. the redirect should be to the exact same URL of the current page to cause a get request to be registered in the browser for that URL. by redirecting to a different URL, anyone can walk up to a computer that was used to register/login using this code and browse back to the form page, which will cause the browser to resubmit the form data, where you can use the browser's developer console network tab to see what the submitted form data is.

Edited by mac_gyver
Link to comment
Share on other sites

here's even more issues -

  1. the email column should be defined as a unique index. this will prevent duplicate email addresses, which could be the cause of the current symptom. then, in the registration code, the exception error handling for the INSERT query would test for a duplicate index error number, and setup a message that the email address is already in use.
  2. when you make the database connection, you need to set the character set to match your database table's character set, so that no character conversion occurs over the connection. this is doubly important when using emulated prepared queries, which you are using but which should be avoided whenever possible, so that sql special characters in a value won't be able to break the sql query syntax.
  3. when you make the database connection, you should set the emulated prepared query setting to false, i.e. you want to use true prepared queries whenever possible.
  4. when you make the database connection, you should set the default fetch mode to assoc, so that you only get the type of fetched data that you want and so that you don't need to specify the fetch mode in each fetch statement.
Link to comment
Share on other sites

@mac_gyver, If you look in bottom of my first posting you find my login form. I dont have a registration form yet because so early in the development process i manually put the testing user accounts in mysql manually. I dont have time to use more time on this now, so i will start develop another system, and this time with email confirmation and a confirmation code. Is less use of time to put a new one together than looking for errors in this login system. I dont think there is only one error. The system has going through many changes through the last year, so it's time to let the old one rest. Any way, thanks for using time for trying to help 😃

Link to comment
Share on other sites

3 minutes ago, LeonLatex said:

@mac_gyver, If you look in bottom of my first posting you find my login form. I dont have a registration form yet because so early in the development process i manually put the testing user accounts in mysql manually. I dont have time to use more time on this now, so i will start develop another system, and this time with email confirmation and a confirmation code. Is less use of time to put a new one together than looking for errors in this login system. I dont think there is only one error. The system has going through many changes through the last year, so it's time to let the old one rest. Any way, thanks for using time for trying to help 😃

You don't need a registration form/page as all you have to do is hash your password that you want to use. That's what I do when I develop my website(s).

Link to comment
Share on other sites

@maxxd@Strider64

Of course, I do. I don't save a plain-text password in the database Have you read through the thread, you would see that your question is so unnecessary, or am I wrong? The password is saved to the "password_hash" column in db, and id hashed with this:

<?php $password = '******'; // Replace the stars with the actual password $hashed_password = password_hash($password, PASSWORD_DEFAULT); echo $hashed_password; // This will output the hashed version of the password for you. Just copy and paste ?>

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.