Despre password-hash inlocuire sha1

Trebuie sa inlocuiesc in codul de logare sha1 (care oricum a fost ceva provizoriu) cu password-hash fiind incepator inca nu stiu bine cum ar trebui sa fac asta.

 if ($_SERVER['REQUEST_METHOD'] === 'POST') {

   $email  = $_POST['email']; 
   $salt = "m23495bnhljhvjjkgvkkuf";
   $password  = $_POST['password'].$salt; 

   //Prevent MySQL Injections 
   $email  = stripslashes($email); 
   $password  = stripslashes($password);

   $email = mysqli_real_escape_string($con, $_POST['email']);
   $password = mysqli_real_escape_string($con, $_POST['password']);
    
    
	$result = mysqli_query($con, "SELECT * FROM `users` WHERE `email` = '" . $email. "' and `password` = '" . sha1($password) . "'");
    
	if ($row = mysqli_fetch_array($result)) {
		$_SESSION['usr_id'] = $row['id'];
		$_SESSION['usr_name'] = $row['name'];
		header("Location: admin.php");
		exit();
	} else {
		$errormsg = "Incorrect Email or Password !";
	}
    
}

Pai inainte de toate, in momentul inregistrarii utilizatorului, trebuie sa salvezi parola in baza de date folosind functia password_hash($password, PASSWORD_DEFAULT);, functie ce are nevoie de doi parametrii, primul parametru fiind parola utilizatorului, ultimul parametru fiind alogoritmul folosit.Bine, mai poate avea inca un parametru, dar nu este atat de important.

Apoi, cand vrei sa faci scriptul ce se ocupa cu autentificarea utilizatorului, trebuie sa preiei parola din baza de date, in functie de email, in cazul tau, daca exista vreo inregistrare, si sa folosesti functia password_verify($password, $row[‘password’]); functie ce are nevoie de doi parametrii, parola introdusa pentru procesul de autentificare si parola preluata din baza de date, aceasta functie va verifica daca se potrivesc si va intoarce un rezultat ca TRUE sau FALSE, de aceea este bine sa folosesti aceasta functie intr-o structura de control ( if/else ) si sa continui procesul de autentificare asa cum doresti tu.

1 Like

Am mai curatat codul un pic el momentan arata asa si totusi ceva undeva nu e ok pentru ca primesc eroare 500 inapoi. Mentionez ca am in baza de date useri conform functie password_hash…

Uite, ti-am facut ceva, poate te ajuta.

<?php
// in development, ne asiguram ca afisarea erorilor este "pornita"
// aceasta este functia folosita pentru a ne asigura ca toate tipurile de erori sunt afisate
error_reporting(E_ALL);

// folosind functia ini_set() putem rescrie anumite setari in fisierul de configurare PHP.ini 
// in cazul nostru dorim ca afisarea erorile sa fie "activata", valoarea 1 ( TRUE )
ini_set('display_errors', 1);

// pornim mecanisul de sesiuni
session_start();

// daca utilizatorul este autentificat, trebuie sa ne asiguram ca nu mai poate accesa pagina de login
if (isset($_SESSION['usr_id'])) {
  header("Location: admin.php");
  exit;
}

// verificam daca cerere HTTP trimisa catre server foloseste metoda POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {

  // primul pas de validare al datelor trimise prin formular, datele fiind stocate in variabila globala $_POST
  // verificam daca au fost trimise date folosind functia empty()
  // aceasta functie verifica daca o variabila este "goala", nu are nici o valoare
  if (empty($_POST['email']) || empty($_POST['password'])) {
    // salvam erorile intr-o sesiune
    $_SESSION['alert']['error'] = "You have to fill all the required fileds";
    // folosim functia header() si scriem un HEADER in raspunsul mesajului HTTP
    // acest HEADER este folosit pentru a face redirect catre o anumita locatie
    // in cazul nostru, pagina login.php ( probabil aceeasi)
    header("Location: login.php");
    // oprim executia scriptului
    exit;
  }

   // salvam datele trimise prin formular.
   $email  = $_POST['email'];
   $password  = $_POST['password'];

   //Prevent MySQL Injections
   $email = mysqli_real_escape_string($con, $_POST['email']);
   $password = mysqli_real_escape_string($con, $_POST['password']);

  // Folosind o interogare de forma "SELECT *" este un bad practice in cazul de fata
  // ai nevoie doar de inregistrarile pentru coloanele id, name si password, nu totul, atentie!!
  $result = mysqli_query($con, "SELECT id, name, password FROM users WHERE email = '{$email}'");

  $user = mysqli_fetch_assoc($result);

  // daca nu a fost gasita nici o inregistrare, sau functia password_verify() are ca rezultat FALSE
  if (!$user || !password_verify($password, $user['password'])) {
    $_SESSION['alert']['error'] = "Invalid email or password, please try again!";
    header("Location: login.php");
    exit;
  }

  // daca totul este bine
  $_SESSION['usr_id'] = $user['id'];
  $_SESSION['usr_name'] = htmlspecialchars($user['name'], ENT_QUOTES); // prevent XSS.
  header("Location: admin.php");
  exit();

}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login page</title>
</head>
<body>
  <?php if (isset($_SESSION['alert']['error'])): ?>
    <p><?=$_SESSION['alert']['error'];?></p>
  <?php endif; ?>
<form action="login.php" method="POST">
<p>Email: <input type="email" name="email"></p>
<p>Password<input type="password" name="password"></p>
<button type="submit">Login</button>
</form>
</body>
</html>
<?php
// trebuie sa stergem aceasta sesiune
// deoarece ea va continua sa persiste
if (isset($_SESSION['alert'])) {
  session_unset($_SESSION['alert']);
}
?>

Eroarea 500, este o eroare datorata serverului, in cazul tau, ai o problema in codul PHP.
Foloseste error_reporting(E_ALL); si ini_set(‘display_errors’, 1); pentru a controla afisarea erorilor.

Da, am rezolvat acolo, nu am mai verificat cu isset() daca variabila exista si nu are valoarea null.

Apropo, vad ca tu folosesti include_once pentru includerea fisierelor, corect?

PHP ofera mai multe posibilitati pentru includerea unui fisier intr-un alt fisier, include, include_once, require si require_once.Diferenta dintre include si require este destul de importanta si iti va spune tie, programatorului, ce instructiune sa folosesti.Deci, daca folosesti include/include_once, in cazul in care fisierul nu exista, PHP emite o eroare, insa executia scriptului continua, ceea ce nu este lucru bun, daca fisierul pe care vrei sa-l incluzi este destul de important? Pai, atunci… o sa ai o mare problema.Ideea este ca atunci cand fisierul nu este gasit, sa se opreasca executia scriptului, astfel, este mai bine sa folosesti require/require_once.Acum, daca fisierul nu este gasit, executia scriptului nu va continua si poti gestiona mai bine aceasta “eroare”, avand nivelul de “EROARE FATALA” ( de retinut faptul ca o eroare fatala opreste executia scriptului).

Poti observa ca exista doua versiuni, require si require_once, pai diferenta dintre ele este simpla, require_once previne includerea unui fiser ce a fost deja inclus.

3 Likes

La codul tau am o mica eroare Undefined index: alert in /login.php on line 73

1 Like

Codul perfect functionabil se afla aici pentru cei care sunt interesati.

Da-i si-o session_regenerate_id(TRUE) la sesiune daca tot scrisesi atata.

Da, dar daca nu-i explici la ce foloseste, tot degeaba, iar ca sa-i poti explica, trebuie sa inteleaga cum functioneaza acest mecanism de persistare a informatiilor.Pentru intelegerea acestui mecanism trebuie sa stie de COOKIE, apoi in cele din urma ( desi reprezinta baza transferului de resurse pe net ) trebuie sa stie si de HTTP.

Pe langa aceasta functie, care este folosita pentru generarea unui nou string de identificare a sesiunii, si care prin introducerea valorii TRUE, rescrie fisierul pe server folosit pentru identificarea sesiunii, se mai poate folosi ini_set(‘session.cookie_httponly’, true);.Schimband valoarea implicita a setarii de configurare pentru sesiuni, “cookie_httponly”, preluarea informatiilor necesare identificarii sesiunii prin folosirea “document.cookie” ( Javascript ) este prevenita.

1 Like