Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Logowanie PHP PDO
Forum PHP.pl > Forum > PHP
seba199696
Cześć wszystkim smile.gif

Napisałem logowanie do serwisu i wszystko działa poprawnie lecz proszę o wasze sugestię na temat bezpieczeństwa skryptu. Proszę o wyrozumiałość smile.gif Pozdrawiam!

Daję kod:

  1. <?php
  2. ?>
  3. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  4.  
  5. <form method="post" action="login.php">
  6. <input type="text" name="email"/>
  7. <input type="password" name="password"/>
  8. <input type="submit" name="submit"/>
  9. </form>
  10. <?php
  11. try
  12. {
  13. //conect
  14. $pdo = new PDO('mysql:host=localhost;dbname=user', 'user', '***');
  15. $pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  16.  
  17. if(isset($_POST['submit'])) {
  18.  
  19. if(filter_var($_POST['email'], FILTER_VALIDATE_EMAIL))
  20. {
  21.  
  22. $password = sha1($_POST['password'].'sad8%$9sdk');
  23.  
  24. $stmt = $pdo -> prepare('SELECT `email`, `password`,`id` FROM `users` WHERE `email` = :email AND `password` = :password');
  25.  
  26. $stmt -> bindValue(':email', $_POST['email'], PDO::PARAM_STR);
  27. $stmt -> bindValue(':password', $password, PDO::PARAM_STR);
  28. $stmt -> execute();
  29.  
  30. $count = $stmt ->rowCount();
  31.  
  32. if($count > 0) {
  33.  
  34. while($row = $stmt -> fetch())
  35. {
  36.  
  37. $_SESSION['status'] = true;
  38. $_SESSION['id'] = $row['id'];
  39. $_SESSION['HTTP_USER_AGENT'] = sha1($_SERVER['HTTP_USER_AGENT'].'dsd#$%^');
  40.  
  41. header('Location: home.php');
  42. }
  43.  
  44. } else {
  45.  
  46. echo "Logowanie zakończone niepowodzeniem!";
  47.  
  48. }
  49.  
  50. } else {
  51.  
  52. echo 'Adres e-mail niepoprawny';
  53.  
  54. }
  55.  
  56. }
  57. }
  58. catch(PDOException $e)
  59. {
  60. echo 'Error: ' . $e->getMessage();
  61. }
  62. ?>
darko
Sprawdzaj jeszcze długość podanych danych i będzie mniej więcej ok.
IceManSpy
A nie lepiej zrobić połączenie dopiero po if(isset) ?
zegarek84
Cytat(IceManSpy @ 15.11.2011, 01:01:45 ) *
A nie lepiej zrobić połączenie dopiero po if(isset) ?

jeśli chodzi o optymalizację to tak - ale na początek nie ma co przesadzać ;]
cycofiasz
Tylko co tam na początku robi ten HTML? Przecież poniżej wysyłasz nagłówki.
seba199696
Chcę umieścić sprawdzenie poprawności hasła smile.gif

- jedną małą literę
- jedną dużą literę
- jedną cyfrę
- jeden znak specjalny
- min 8 znaków
- max 30 znaków

Podaję kod:

  1. <?php
  2.  
  3. $pass = "Password!1";
  4.  
  5. if (preg_match("/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-]).{8,30}$/",$pass)) {
  6.  
  7. //true
  8.  
  9. }
  10.  
  11. ?>


Co o tym myślicie?
abort
IMO Wygląda nieźle.
zegarek84
jako, że rozumiem wyrażenia regularne, to mogę ze spokojnym sumieniem napisać, iż znaków można wprowadzić grubo więcej niż 30 a i poprawne hasło z założenia będzie błędne - przykład:
!0aAAAAA
z kolei błędne hasło które na bank przejdzie:
...............A...............a...............0...............!...............
na wyrażeniu całości tak nie zrobisz , i choć całe wyrażenie nie jest najlepsze to koniec choćby nawet znaczy .{8,30} - minimum 8 max 30 dowolnych znaków, z kolei ".*" znaczy to samo co 0 i więcej dowolnego znaku...

ps. nie wierzę, że hasło w podanym kodzie pasuje do wzorca ;D - gdyż nie może
______________________

edit
mój błąd
seba199696
Napisałeś że haslo ...............A...............a...............0...............!............... przejdzie a to nie prawda pokazuje false
abort
Cytat(zegarek84 @ 16.11.2011, 00:44:35 ) *
ps. nie wierzę, że hasło w podanym kodzie pasuje do wzorca ;D - gdyż nie może


A jednak pasuje. Wystarczy wrzucić regexpa do pliku php i odpalić go w przeglądarce, co serdecznie polecam.
Pasuje także zmiana kolejności liter, cyfr i znaków specjalnych (czego na pierwszy rzut oka nie widziałem).
zegarek84
rzeczywiście mój błąd - aż mi wstyd - nie trzeba wrzucać do pliku, można z linii poleceń sprawdzić...

chyba przegapiłem znak "=" i potraktowałem jako ":", czyli zamiast (?=) myślałem w kategorii (?:)... jest jeszcze jedno przydatne grupowanie (?!) - czyli ma się nie dopasować do tego co w środku...
seba199696
Wkleję za niedługo poprawiony skrypt smile.gif

  1. <?PHP
  2. if(isset($_POST['submit'])) {
  3.  
  4. if (preg_match("/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-]).{8,30}$/",$_POST['password'])) {
  5.  
  6. if(preg_match('/^[a-zA-Z\.\-\_]+\@[a-zA-Z0-9\.\-\_]+\.[a-z]{2,4}$/D', $_POST['email'])) {
  7.  
  8. try
  9. {
  10. $pdo = new PDO('mysql:host=localhost;dbname=user', 'user', '***');
  11. $pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  12.  
  13. $password = sha1($_POST['password'].'sad8%$9sdk');
  14.  
  15. $stmt = $pdo -> prepare('SELECT `email`, `password`,`id` FROM `users` WHERE `email` = :email AND `password` = :password');
  16.  
  17. $stmt -> bindValue(':email', $_POST['email'], PDO::PARAM_STR);
  18. $stmt -> bindValue(':password', $password, PDO::PARAM_STR);
  19. $stmt -> execute();
  20.  
  21. $count = $stmt ->rowCount();
  22.  
  23. if($count > 0) {
  24.  
  25. while($row = $stmt -> fetch())
  26. {
  27.  
  28. $_SESSION['status'] = true;
  29. $_SESSION['id'] = $row['id'];
  30. $_SESSION['HTTP_USER_AGENT'] = sha1($_SERVER['HTTP_USER_AGENT'].'dsd#$%^');
  31.  
  32. // last active the user ip
  33. $stmt = $pdo -> prepare('UPDATE `users` SET `ip` = :ip WHERE `id` = :id');
  34.  
  35. $stmt -> bindValue(':ip', $_SERVER['REMOTE_ADDR'], PDO::PARAM_STR);
  36. $stmt -> bindValue(':id', $row['id'], PDO::PARAM_STR);
  37.  
  38. $stmt -> execute();
  39. //
  40.  
  41. header('Location: index.php');
  42. }
  43.  
  44. }
  45. }
  46.  
  47. catch(PDOException $e)
  48. {
  49. echo 'Error: ' . $e->getMessage();
  50. }
  51. } else { echo "Email error"; }
  52. } else { echo "Hasło error"; }
  53. } else { echo "Formularz error"; }
  54.  
  55. ?>
  56.  
Crozin
1. Po co w procesie logowania sprawdzasz poprawność formatu emaila / hasła?
2. Po nagłówku Location powinieneś przerwać działanie skryptu i wyświetlić stronę z informacją o wykonaniu przekierowania do innego URL.
3. Zamiast paskudnych, zagnieżdżonych IF-ELSE-ów, możesz napisać:
  1. if (!...) {
  2.  
  3. }
  4.  
  5. if (!...) {
  6.  
  7. }
  8.  
  9. // tutaj kod, gdy wszystko w porządku


seba199696
Poprawiłem to smile.gif

Wydaje mi się że wszystko jest okej smile.gif

  1. <?php
  2.  
  3. $password = $_POST['password'];
  4. $email = $_POST['email'];
  5.  
  6.  
  7. function checkout_password($password)
  8. {
  9. if(preg_match("/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-]).{8,30}$/",$password))
  10. return true;
  11. else
  12. return false;
  13. }
  14.  
  15. function checkout_email($email)
  16. {
  17. if(preg_match('/^[a-zA-Z\.\-\_]+\@[a-zA-Z0-9\.\-\_]+\.[a-z]{2,4}$/D', $email))
  18. return true;
  19. else
  20. return false;
  21. }
  22.  
  23.  
  24. if (checkout_email($email) and checkout_password($password) and isset($_POST['submit']))
  25. {
  26. try
  27. {
  28.  
  29. $pdo = new PDO('mysql:host=localhost;dbname=user', 'user', 'password');
  30. $pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  31.  
  32. $passwordhash = sha1($password.'sad8%$9sdk');
  33.  
  34. $stmt = $pdo -> prepare('SELECT `email`, `password`,`id` FROM `users` WHERE `email` = :email AND `password` = :password');
  35. $stmt -> bindValue(':email', $email, PDO::PARAM_STR);
  36. $stmt -> bindValue(':password', $passwordhash, PDO::PARAM_STR);
  37. $stmt -> execute();
  38.  
  39. $count = $stmt ->rowCount();
  40.  
  41. if($count > 0)
  42. {
  43.  
  44. while($row = $stmt -> fetch())
  45. {
  46.  
  47. $_SESSION['status'] = true;
  48. $_SESSION['id'] = $row['id'];
  49. $_SESSION['HTTP_USER_AGENT'] = sha1($_SERVER['HTTP_USER_AGENT'].'dsd#$%^');
  50.  
  51.  
  52. header('Location: index.php');
  53. }
  54.  
  55. }
  56.  
  57. }
  58.  
  59. catch(PDOException $e)
  60. {
  61. echo 'Error: ' . $e->getMessage();
  62. }
  63.  
  64. } else {
  65.  
  66. header('Location: login.html');
  67.  
  68. }
  69.  
  70.  
  71.  
  72. ?>
cycofiasz
Po co pętla while? Nie sądzę by było więcej userów o tym samym emailu i haśle.
Podczas pisania polecam pracować z wyświetlaniem błędów typu E_NOTICE.
seba199696
Czyli zamiast:

  1. while($row = $stmt -> fetch())

Użyć:
  1. $row = $stmt -> fetch();

?
Inscure
Tak
celbarowicz
Podobno : $stmt -> closeCursor();
http://pl.wikibooks.org/wiki/PHP/Biblioteka_PDO
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.