PDO logowanie

0

Witam. Mam do Was dwa pytania. Do tej pory działałem na MySql, chcialem przejść na PDO, już mam skrypt logowania i rejestracji, lecz mam problem z lekkim przerobieniem tych skryptów. Chcę aby skrypt rozpoznawał nick, który nie pasuje do tego znajdującego się w bazie i wyświetlał odpowiendi komunikat, tak samo z hasłem. Ogólnie wiem jak to zrobić, lecz nie wiem w którym miejscu programy dodać owe instrukcję warunkowe.
Oto kod:

$db = new PDO('mysql:host=host;dbname=baza', 'user', 'haslo', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'")) or die();
         
if(isset($_POST['wyslano'])){ //Sprawdzamy, czy submit został wciśnięty
    //Usuwamy białe znaki z przesłanych danych
    $nick = trim($_POST['nick']);
    $haslo = trim($_POST['haslo']);
 
    $stmt = $db->prepare("SELECT * FROM uzytkownicy WHERE nick=:nick AND haslo=:haslo");
    $stmt->bindValue(":nick", $nick, PDO::PARAM_STR);
    $stmt->bindValue(":haslo", $haslo, PDO::PARAM_STR);
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if($stmt->rowCount()!=0){
        echo "Zalogowałeś się!";
        session_start();
        $_SESSION['nick'] = true;
        $_SESSION['nick'] = $row['nick'];
    }
    else{
        echo '<div style="color:red">Login i/lub hasło są nieprawidłowe</div>';
        form();
    }
}
else form();
 

Pytanie 2:
Czy PHP data object automatycznie warunkuje wykonanie jakiegoś zadania na stronie? że możemy daną ilość razy próbować się zalogować, później musimy odczekać jakąś ilość czasu i wtedy możemy próbować dalej?

0

Musisz trochę kod zmienić.

  1. Wyciągnij użytkownika z bazy tylko po loginie
  2. Logika na podstawie wyniku
    a) Jeżeli nie ma użytkownika w bazie (count == 0), to znaczy że użytkownik pomylił login
    b) Jeżeli jest użytkownik ale hasło się nie zgadza, to znaczy ze pomylił hasło
    c) Jeżeli wszytko ok to idziesz dalej

Kiedyś uważało się to za "best practice" by własnie takich informacji nie wyświetlać, żeby nie dało się brute forcem wyciągnąć wszystkich użytkowników.

Obawiam się też że przechowujesz hasła w bazie jako clear text?

0

zamiast SELECT * FROM uzytkownicy WHERE nick=:nick AND haslo=:haslo napisz SELECT * FROM uzytkownicy WHERE nick=:nick i jak rowCount == 0 to nie ma usera a jak $row['nick'] != $haslo to złe hasło
2. nie - trzeba zrobić samemu

0

Może się mylę, ale PDO chyba nie ma wbudowanego "rate limiting". Użył bym gotowej biblioteki, np: https://github.com/bandwidth-throttle/token-bucket

0

Rozumiem dzięki.
Lecz chciałbym dowiedzieć się, dlaczego teraz gdy wpiszę w jakieś miejsce instrukcję warunkową porównującą podany nick do tego z bazy, logowanie nie działa. Niezależnie czy dam ją po instrukcji porównującą nicki i hasła, czy też przed.

Mogę zastosować szyftowanie hasła, fakt.

0

Od kiedy to hasła mają być unikatowe? Może wyjdźmy od tego:

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `email` varchar(254) NOT NULL,
  `username` varchar(32) NOT NULL DEFAULT '',
  `password` varchar(64) NOT NULL,
  `logins` int(10) UNSIGNED NOT NULL DEFAULT '0',
  `last_login` int(10) UNSIGNED,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `uniq_username` (`username`),
  UNIQUE KEY `uniq_email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8; 

Czyli w takim przypadku przy rejestracji użytkownika ma być unikalny e-mail oraz username a co do hasła to w tym przypadku jest to hash jako SHA-256:

   $password = 'qwerty12345';
   $key = 'gSxx8rX4tnbK8Ne';
   $hash = hash_hmac('sha256', $password, $key);

I hash tego hasła będzie zapisywany w bazie podczas rejestracji a potem rzecz jasna podczas logowania również należy hash-ować wprowadzone w formularzu hasło i porównywać je z tym co jest w bazie. Ale nie jest sprawdzane jako unikatowe.

Tutaj w przypadku gdy login oraz e-mail nie będą unikatowe powinien zostać wyrzucony jakiś wyjątek który zresztą można obsłużyć. Natomiast można to też sprawdzać czy dany login istnieje w bazie przy użyciu PDO podczas rejestracji.

0

Zrobiłem to w ten sposób

    $stmt = $db->prepare("SELECT * FROM uzytkownicy WHERE nick=:nick");
    $stmt->bindValue(":nick", $nick, PDO::PARAM_STR);
	$stmt->bindValue(":haslo",$haslo,PDO::PARAM_STR);
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if($stmt->rowCount()==0){
        echo "Błędny nick"; 
		form();
    }
	else if($row['nick'] != $haslo)
	{
		echo 'Błędne Hasło';
		form();
	}else if($stmt->rowCount()!=0)
	{

		echo 'Zalogowano!';
		
        session_start();
        $_SESSION['nick'] = true;
        $_SESSION['nick'] = $row['nick'];
		//header("Location:pologowaniu.php");
	
	}
}
else form(); 

Pokazuje informacje o błędnym haśle i nicku, lecz nie loguje jak nick i hasło są poprawne.

0

No nie tak.

$nick = $_POST['nick'];
$haslo = $_POST['haslo'];

// zakladam ze $db jest utworzone przez polaczenie PDO
$stmt = $db->prepare('SELECT * FROM uzytkownicy WHERE nick=:nick AND haslo=:haslo');
$stmt->execute(array(':nick' => $nick, ':haslo' => $haslo));
if ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
    echo 'Zalogowano pomyslnie';
}
else
{
    echo 'Blad logowania';
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1