Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP]Logowanie 2-etapowe (projekt)
Forum PHP.pl > Forum > Przedszkole
gloweres
Hej, zaprojektowałem proste logowanie 2-etapowe (na maila przychodzi kod do logowania po wpisaniu hasła).
Logowanie to jest używane tylko przez 2 osoby ale do bardzo wrażliwych danych więc mam następujące pytanie: czy jest bezpieczne? Może popełniłem jakiś błąd który może powodować "włam"? Dzięki z góry za odpowiedź smile.gif


login.php
  1. <?php
  2.  
  3.  
  4. require 'dbsoft.php';
  5.  
  6. $password = $_POST['password'];
  7.  
  8. $email = htmlentities($_POST['email'], ENT_QUOTES, "UTF-8");
  9.  
  10. $sekret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  11.  
  12. $sprawdz = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$sekret.'&response='.$_POST['g-recaptcha-response']);
  13.  
  14. $odpowiedz = json_decode($sprawdz);
  15.  
  16. if ($odpowiedz->success==false)
  17. {
  18. $_SESSION['e_bot']="Potwierdź, że nie jesteś botem!";
  19. header('Location: ../login.php');
  20. exit();
  21. }
  22. $sql = 'SELECT * FROM account WHERE email=?';
  23. $statement = $connection->prepare($sql);
  24. $statement->execute([$email]);
  25. $oz = $statement->rowCount();
  26.  
  27. if($oz>0){
  28.  
  29. $row = $statement->fetchAll(PDO::FETCH_OBJ);
  30.  
  31. foreach($row as $rows):
  32. $password_base = $rows->password;
  33. $email = $rows->email;
  34. $id_base = $rows->id;
  35. endforeach;
  36.  
  37. if (password_verify($password, $password_base))
  38. {
  39.  
  40. $_SESSION['verify'] = true;
  41. $_SESSION['id_session'] = $id_base;
  42.  
  43. function random(int $i)
  44. {
  45. return substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($i/strlen($x)) )),1,$i);
  46. }
  47.  
  48. $code = random(35);
  49. $now = time() + 900;
  50. $time = date("Y-m-d H:i:s");
  51.  
  52. $sql = "INSERT INTO verify_code (id_user, code, date, status_code) VALUES (?, ?, ?, ?)";
  53. $connection->prepare($sql)->execute([$id_base, $code, $now, 0]);
  54.  
  55. $message="Kod do weryfikacji:\n\n$code\n\nWiadomosc zostala wygenerowana automatycznie: $time";
  56. $sender="From: domena.pl";
  57. @mail($email, "Kod weryfikacyjny", $message, $sender);
  58.  
  59. unset($_SESSION['error']);
  60.  
  61. $statement = null;
  62. $connection = null;
  63.  
  64. header('Location: verify.php');
  65.  
  66. }
  67. else
  68. {
  69.  
  70. $_SESSION['error'] = '<span style="color:red">Nieprawidłowy login lub hasło!</span>';
  71. $statement = null;
  72. $connection = null;
  73. header('Location: ../login.php');
  74.  
  75. }
  76.  
  77. } else {
  78.  
  79. $_SESSION['error'] = '<span style="color:red">Nieprawidłowy login lub hasło!</span>';
  80. $statement = null;
  81. $connection = null;
  82. header('Location: ../login.php');
  83.  
  84. }
  85.  
  86. $statement = null;
  87. $connection = null;
  88.  
  89. ?>



verify_check.php:
  1. <?php
  2.  
  3.  
  4. if (!isset($_SESSION['verify']))
  5. {
  6. header('Location: ../login.php');
  7. exit();
  8. }
  9.  
  10.  
  11. if(empty($_POST["code"]) || !isset($_POST["code"])){
  12.  
  13. $_SESSION['error'] = '<span style="color:red">Nie podano kodu</span>';
  14. header('Location: verify.php');
  15.  
  16. }
  17.  
  18. $code = htmlentities($_POST["code"], ENT_QUOTES, "UTF-8");
  19.  
  20. require '../database_connect/dbsoft.php';
  21.  
  22. $sql = 'SELECT * FROM verify_code WHERE code=?';
  23. $statement = $connection->prepare($sql);
  24. $statement->execute([$code]);
  25.  
  26. $row = $statement->fetchAll(PDO::FETCH_OBJ);
  27.  
  28. foreach($row as $rows):
  29. $id_user = $rows->id_user;
  30. $date = $rows->date;
  31. $code_base = $rows->code;
  32. $status_base = $rows->status_code;
  33. $ide = $rows->id;
  34. endforeach;
  35.  
  36. $now = time();
  37.  
  38. if($status_base == 0){
  39. if($code_base == $code){
  40.  
  41. if($_SESSION['id_session'] == $id_user){
  42.  
  43. if($now <= $date){
  44.  
  45. $_SESSION['admin'] = true;
  46.  
  47. $st = 1;
  48.  
  49. $sql = "UPDATE verify_code SET status_code=? WHERE id=?";
  50. $statement = $connection->prepare($sql);
  51. $statement->execute([$st, $ide]);
  52.  
  53. unset($_SESSION['verify']);
  54.  
  55. $statement = null;
  56. $connection = null;
  57.  
  58. header('Location: ../../');
  59. exit();
  60.  
  61. }else{
  62. echo 'Czas minał';
  63. }
  64.  
  65. }else{
  66. echo 'To nie ty!';
  67. }
  68.  
  69. }else{
  70. echo 'Nieprawidłowy kod';
  71. }
  72. }else{
  73. echo 'Kod został zużyty';
  74. }


Jeśli jest dobrze to proszę też o odpowiedź smile.gif
SmokAnalog
Popraw wcięcia.
Pyton_000
jedynie bym usuwał użyte kody, nie ma sensu ich trzymać. Poza tym da się żyć, ale bez composera co to za życie biggrin.gif
gloweres
Cytat(Pyton_000 @ 10.11.2020, 20:58:00 ) *
jedynie bym usuwał użyte kody, nie ma sensu ich trzymać. Poza tym da się żyć, ale bez composera co to za życie biggrin.gif


Postanowiłem przechowywać je w bazie żeby mieć logi kto kiedy się logował (bo zapisuje id użytkownika, datę zalogowania oraz czy kod został wykorzystany)
gino
można by się przyczepić jeszcze do generowania samych kodów, istnieje prawdopodobieństwo powtórzenia się kodu, więc albo jak Pyton pisał usuwać, albo jakiś mocniejszy algorytm np GUID
dublinka
Ja jeszcze przed samym przypisaniem sesji wygenerowalbym nowe id sesyjne
Pyton_000
Cytat(gloweres @ 10.11.2020, 21:41:13 ) *
Postanowiłem przechowywać je w bazie żeby mieć logi kto kiedy się logował (bo zapisuje id użytkownika, datę zalogowania oraz czy kod został wykorzystany)


Sam kod powinien mieć możliwy krótki czas życia np. 15min.
Do logowania możesz mieć oddzielną tabelkę z historią i tam możesz sobie zapisywać ID usera, datę, i czy udane logowanie czy nie. Wtedy możesz nawet wykrywać że ktoś chce sobie powłamywać się.

Co do kolizji kodów wspominany przez @gino to prawda. jest libka do php do generowania UUIDv4 (najbardziej randomowy) https://github.com/ramsey/uuid
Ale jesli to jest taki prosty kod jak go pokazujesz to nie ma sensu szaleć.
dublinka
Cytat(gino @ 10.11.2020, 21:54:23 ) *
można by się przyczepić jeszcze do generowania samych kodów, istnieje prawdopodobieństwo powtórzenia się kodu

Z takim ciagiem praktycznie niemozliwe
viking
Włącz sobie jeszcze pełne raportowanie błędów i popraw wszystko. Tak logicznie robisz też insert kodu który za chwilę może się wywalić na mail() i nic z tym nie robisz np rollback transakcji.
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.