Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Logowanie na sesjach i mysql :P
Forum PHP.pl > Forum > Przedszkole
marian2299
Napisałem własne skrypty, działają i wgl, ale muszą zostać zabezpieczone. W związku z tym piszcie, czy napisałem w miarę ok, czy są rażące widoczne błędy, itp.
Plik logowanie.php
  1. <?php
  2. sesion_start(); //rozpoczęcie sesji
  3.  
  4. $login = mysql_real_escape_string($_POST['login']); //określenie zmiennej login, dodanie backshalsy
  5. $haslo = mysql_real_escape_string(md5($_POST['haslo'])); //określenie zmiennej haslo, dodanie backshalsy,kodowanie md5
  6.  
  7. if ($login != "" && $haslo != ""){ //sprawdzanie czy zmienne nie są puste
  8.  
  9. $zapytanie = "SELECT * FROM `uzytkownicy` WHERE login="'. $login.'" and haslo="'.$haslo.'" "; //zapytanie
  10. $uzytkownik = mysql_fetch_array(mysql_query($zapytanie) or die("Wystąpił nieoczekiwany błąd.")); //tworzymy tablicę
  11.  
  12. $_SESSION['login'] = $uzytkownik['login']; //określamy zmienną sesyjną login
  13. $_SESSION['haslo'] = $uzytkownik['haslo']; //określamy zmienną sesyjną haslo
  14. $_SESSION['id'] = $uzytkownik['id']; //określamy zmienną sesyjną id
  15. echo "Zostałeś zalogowany jako: ".$_SESSION['login'].""; //jeśli wszystko ok, wyświetlamy login
  16. }
  17. else {
  18. echo 'Podałeś błędne dane, spróbuj ponownie.'; //jeśli nie baj baj
  19. }
  20.  
  21. ?>


Czy wszystko robię ok ? Czy jest to odporne na SQJ injection ? Macie może jakieś sugestie ?
Czy w pliku tylko dla zalogowanych w zupełności wystarczy:
  1. <?php
  2. if (!isset($_SESSION['login']) || !isset($_SESSION['haslo'])) {
  3. header("location:index.php"); // Przekierowanie do index.php
  4. }
  5. ?>
Fifi209
Najpierw sprawdź czy zmienne są w post a potem dopiero przeleć mysql_real_escape_string.

Dalej... polecam zainteresować się wyrażeniami regularnymi pcre
marian2299
A czy `przelecenie mysql_real_escape_string` po pustych zmiennych może dać niepożądane skutki ?, if ($login != "" && $haslo != ""){ to po `przeleceniu` nie wystarczy ?

Co do tych wyrażeń, poczytam, ale jutro (ciężki dzień haha.gif).

A ogólnie ten kod może być ?
Fifi209
Spróbuj użyć funkcji na czymś co nie istnieje...

W dodatku umknęło mi, niedopuszczalne jest zapisywanie hasła w sesji. (nawet hashu)
marian2299
Czyli zostawić id i login? Będzie działać wszystko?
Fifi209
Cytat(marian2299 @ 17.08.2009, 01:07:08 ) *
Czyli zostawić id i login? Będzie działać wszystko?


Właściwie jeżeli nie będziesz wykorzystywał tych informacji to możesz zrobić po prostu:

  1. $_SESSION['login'] = true;


I potem na podstronach sprawdzać:
  1. if ($_SESSION['login'] === true) {
  2. // zalogowany
  3. }else{
  4. // niezalogowany
  5. }


Działać, będzie nawet w pierwotnej wersji, lecz pisałeś chyba z myślą o przebudowie...
Jak wspomniałem, wyrażenia regularne i możesz odpuścić wtedy mysql_real_escape_string (na haśle możesz od razu usunąć bo i tak hashujesz)
radabus
Podpinając się pod ten temat (gdyż trochę się nim sugerowałem), chciałem zapytać o wskazówki odnośnie takiego prostego skryptu, który wysmażyłem. Plik login.php pobiera dane od formularza w pliku index.php i wygląda następująco:

  1. <?php
  2. include ("db_connect.php");
  3.  
  4. // sprawdzamy dane w tablicy $_POST
  5. if ((isset($_POST['username'])) && (isset($_POST['password']))) {
  6. if ((($_POST['username']) == "") || (($_POST['password']) == "")) {
  7. // dla pustych zmiennych w $_POST (uzytkownik nic nie wpisal) automatycznie wracamy do logowania
  8. header('Location: index.php');
  9. }
  10. else {
  11. $username = $_POST['username'];
  12. $password = sha1($_POST['password']);
  13. $zapytanie_do_bazy = sprintf("SELECT * FROM logowanie WHERE uzytkownicy_username='%s'", mysql_real_escape_string($username));
  14. $wynik_zapytania = mysql_query($zapytanie_do_bazy) OR die(mysql_error());
  15. $tablica_pomocnicza = mysql_fetch_assoc ($wynik_zapytania);
  16. if ($tablica_pomocnicza['uzytkownicy_username'] == $passwordd) {
  17. // haslo sie zgadza - możemy przejść do pliku plik_chroniony.php
  18. $_SESSION['zalogowany'] = true;
  19. header('Location: plik_chroniony.php');
  20. }
  21. else {
  22. // haslo sie nie zgadza - wracamy do logowania
  23. // czyli kierujemy teraz użytownika z powrotem do logowania, wyświetlając odpowiedni komunikat
  24. }
  25. }
  26. }
  27. else {
  28. // jesli wystapilo bezposrednie odwolanie do pliku login.php, zamiast użycie formularza w pliku index.php, to kierujemy z powrotem do index.php
  29. header('Location: index.php');
  30. }
  31. ?>


Jeśli mogę prosić o jakąś opinię - jeśli coś jest źle, to jak poprawić?

pozdrawiam
Radek
erix
Co źle? A sam sprawdzić nie możesz? Audyt? Giełda ofert.
radabus
Sprawdzam i działa. Chodzi mi tylko o podpowiedź odnośnie "dobrych praktyk programistycznych", czy nie popełniłem jakiegoś "faux-pas" w kodzie. Napisałem przecież "jeśli coś jest źle", a nie "co jest źle" smile.gif

Bardziej zależało mi na poradzie typu "to-czy-tamto można zrobić lepiej, wydajniej, tu niepotrzebnie np. duplikujesz dane". Ogółem działać działa i jestem z siebie zadowolony, że opanowałem ten temat. Tylko żeby nie popadać w samozachwyt wolę się upewnić, że czegoś nie pochrzaniłem winksmiley.jpg
Suh
Mam takie uwagi do obu Panów smile.gif
@radabus:
Te if'y :
  1. if ((isset($_POST['username'])) && (isset($_POST['password']))) {
  2. if ((($_POST['username']) == "") || (($_POST['password']) == "")) {

można zastąpić po prostu tym :
  1. if(!empty($_POST['username']) && !empty($_POST['password'])) {

efekt będzie ten sam, a przynajmniej jeden warunek mniej do sprawdzania - tym bardziej ze w przypadku niepoprawnych danych oba if'y kierowaly do pliku index.php.

Ponadto - i to się tyczy do Was obu - walidacja danych exclamation.gif WAŻNE jest założenie, że KAŻDE dane pochodzące z zewnątrz, a szczególnie GET, POST - są niebezpieczne ! Dlatego też (tak jak wcześniej proponował fifi209) - bez wyrażeń regularnych się nie obejdzie.

@marian2299 - przeanalizuj sobie kod radabus'a. Bezpieczne logowanie powinno wyglądać właśnie tak jak on to zrobił - na podstawie loginu wyciągamy hasło z bazy i porównujemy z tym, które podano w formularzu.
Niestety ale Twój kod nie jest bezpieczny pod względem SQL Injection. Wystarczy w polu gdzie podajesz login użytkownika wpisać: " ' OR 1=1 " lub coś podobnego i masz dostęp do systemu.
radabus
Cytat(Suh @ 19.08.2009, 21:59:31 ) *
Ponadto - i to się tyczy do Was obu - walidacja danych exclamation.gif WAŻNE jest założenie, że KAŻDE dane pochodzące z zewnątrz, a szczególnie GET, POST - są niebezpieczne ! Dlatego też (tak jak wcześniej proponował fifi209) - bez wyrażeń regularnych się nie obejdzie.


@Suh: czyli samo


nie wystarczy? Najpierw trzeba wyrażeniami regularnymi sprawdzić, czy string przypadkiem nie zawiera niedozwolonych znaków i dopiero wtedy puścić go do MySQLa? Dobrze rozumiem? Bo jeśli mysql_real_escape_string nie wystarcza, to albo ja coś źle rozumiem, albo manual wprowadza w błąd winksmiley.jpg Jest tam przecież napisane, że...

Cytat
tak przygotowanego łańcucha można bezpiecznie użyc w funkcji mysql_query()

Samo napisanie sprawdzenia wyrażenia regularnego dla prostego ciągu znaków jak nazwa użytkownika nie powinno być trudne (chociaż jeszcze w pełni tego nie opanowałem), ale w takim razie po co używać mysql_real_escape_string? Takie dublowanie roboty wtedy jest winksmiley.jpg
kamillo121
Witam, nie będę zaczynał nowego tematu bo pytanie trochę ma do tego tematu , otóż przy skrypcie logowania , jak sprawdzam potem czy są isset zmienne $_POST , potem czy nie są puste i pasują do wyrażenia regularnego(preg_match) , potem w skrypcie ta metoda mysql_real_escape_string, to czy to mi da dosyć bezpieczny skrypt logowania ?
erix
Przeczytaj przyklejony wątek o bezpieczeństwie, dopiero potem pytaj... :X
kamillo121
Cytat(erix @ 20.08.2009, 00:09:51 ) *
Przeczytaj przyklejony wątek o bezpieczeństwie, dopiero potem pytaj... :X


Przeczytałem, i pytam (pytanie poprzednie ) Bo nie znalazłem odpowiedzi na moje pytanie sadsmiley02.gif ...
Suh
Lepiej zrobić o jedno zabezpieczenie więcej, niż mniej.. Na pewno to nie zaszkodzi, a może co najwyżej poprawić sytuację.
Poza tym mysql_real_escape_string() może Ci co najwyżej sprawdzić czy nie ma w podanym ciągu takich znaków jak np. ' " czy coś podobnego. A wyrażenia regularne mogą ponadto np. sprawdzać czy w loginie nie ma cyfr lub podkreśleń czy innych takich znaków, których sobie po prostu nie życzysz.
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.