Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Kodowanie haseł w MySQL
Forum PHP.pl > Forum > Bazy danych > MySQL
Wujek01
Witam
Mam problem z weryfikacją. Hasło oraz login przechowywane są w tabeli. Oczywiście login jest zwykłym textem typu varchar natomiast hasło też jest typu varchar jednak zakodowane funkcją PASSWORD().
Sprawdzanie odbywa się przez:
  1. <?php
  2. $zapytanie = "select count(*) FROM tabela WHERE nazwa='$name' and haslo=PASSWORD('$haslo')";
  3. ?>

Po localhoscie wszystko działa idealnie jednak problem zaczyna sie po wczytaniu bazy na serwer. Niemogę się zalogować na strone gdyż hasło się nie zgadza. Ręczna zmiana haseł bezpośrednio na serwerze przez phpMyAdmina nie pomaga (bez szyfrowania hasła oczywiście wszystko działa). Baze mam na yoyo.pl (ver bodaj MySQL 5.0.20). Co może być nie tak questionmark.gif Jak inaczej jeszcze można szyfrować hasła w tabeli. Próbowałem funkcją md5() ale sytuacja jest identyczna.
nospor
Prawdopodobnie chodzi oto, iz u siebie masz inna wersje mysql. funkcja password w roznych wersjach mysql zwraca hashe innej dlugosci, wiec ci sie nie zgadza:
http://dev.mysql.com/doc/refman/5.0/en/password-hashing.html

Lepiej hashowac po stronie php przy uzyciu powiedzmy md5 i takie wyniki wkladac do zapytania. Oczywiscie w bazie tez bys musial juz miec wpisy z php zrobione
bendi
Cytat(nospor @ 7.06.2006, 13:07 ) *
Oczywiscie w bazie tez bys musial juz miec wpisy z php zrobione


No to akurat nie jest do końca prawda: http://dev.mysql.com/doc/refman/5.0/en/enc...-functions.html
Wujek01
Wielkie dzięki za pomoc nospor. Poradziełm sobie tak:
  1. <?php
  2. $haslo = $_POST['password'];
  3. $haslo1 = md5($haslo);
  4. $zapytanie = "select count(*) FROM tabela WHERE nazwa='$name' and haslo='$haslo1'";
  5. ?>

Niewiem dlaczego ale wpisanie bezpośrednio w zapytanie kodowania md5:
  1. <?php
  2. $zapytanie = "select count(*) FROM tabela WHERE nazwa='$name' and haslo=md5('$haslo')";
  3. ?>

wyrzucało błedy że niemożna przesłać zapytania. Ale to już nieistotne, porównywanie działa poprawnie.
bendi
Cytat(Wujek01 @ 7.06.2006, 14:35 ) *
porównywanie działa poprawnie.

Nie widzę struktury bazy ale jak jesteś pewien że działa tak poprawnie to spróbuj:
Kod
INSERT INTO tabela (nazwa, haslo) values( 'dupa', md5('dupa'));

A później
Kod
SELECT count(*) FROM tabela WHERE nazwa = 'dupa' and lower( md5( 'dupa' ) );
-- oraz
SELECT count(*) FROM tabela WHERE nazwa = 'dupa' and upper( md5( 'dupa' ) );
-- i
SELECT count(*) FROM tabela WHERE nazwa = 'dupa' and md5( 'dupa' );


Jeżeli w pierwszych dwóch przypadkach dostaniesz 0 to wszystko gra, ale jak dostaniesz 1 to znaczy że coś nie gra, otóż przypuszczalnie masz wtedy zadeklarowaną kolumnę w bazie jako CHAR/VARCHAR, w takim przypadku żeby wymusić case sensitivity trzeba dodać jeszcze do deklaracji kolumny BINARY i będzie wsio ok.
Wujek01
Struktura tabeli jest bardzo prosta:
idskl - smallint, auto_increment
nazwa - varchar(50)
haslo - varchar(32)

Jeśli chodzi o powyższe zapytania to wszystkie zwracają 1-nke.
bendi
Zmień hasło na binary. W przypadku stringów jednobajtowych (a md5 generuje tylko takowe) wymusi to sprawdzanie uwzględniające wielkość liter. Ponadto dla stałych ciągów znaków lepiej jest zastosować typ CHAR, różnica w porównaniu z VARCHAR jest taka, że ten drugi przechowuje zmienne długości ciągów + 1 bajt na opisanie ich długości, co w tym przypadku spowoduje przechowywanie zawsze o jednego bajta za dużo.

  1. CREATE TABLE tabela (
  2. idskl smallint AUTO_INCREMENT,
  3. nazwa varchar(50),
  4. haslo CHAR(32) BINARY
  5. )
nospor
Cytat
VARCHAR jest taka, że ten drugi przechowuje zmienne długości ciągów + 1 bajt na opisanie ich długości, co w tym przypadku spowoduje przechowywanie zawsze o jednego bajta za dużo.

@bendi masz racje. Tylko gdzie kiedys czytalem, że jesli w tabeli istnieją jednoczesnie pola CHAR i VARCHAR to te typu CHAR są i tak niejawnie konwertowane do VARCHAR, wiec w tym przypadku co podales to i tak bez roznicy
bendi
Cytat(nospor @ 8.06.2006, 10:13 ) *
@bendi masz racje. Tylko gdzie kiedys czytalem, że jesli w tabeli istnieją jednoczesnie pola CHAR i VARCHAR to te typu CHAR są i tak niejawnie konwertowane do VARCHAR, wiec w tym przypadku co podales to i tak bez roznicy

Chyba nie całkiem o to chodzi, bo owszem nijawna konwersja zachodzi tylko wtedy gdy MySQL uzna, że lepiej jest stosować CHAR zmiast VARCHARA. Może sie tak zdarzyć w przypadku gdy zdefiniowana długość pola ma poniżej 3 znaków, bo wtedy w przypadku pola VARCHAR i przy założeniu że większość danych będzie miała dokładnie 3 znaki dla tego typu musimy przehowywać jeszcze długość, więc w sumie 4 bajty, a CHAR zawsze będzie trzymał 3.

I to chyba tyle niejawnej konwersji podczas tworzenia tabel, jeżeli gdzieś znajdzisz linka do zachowania o którym piszez to z chęcią poczytam smile.gif
nospor
Cytat
jeżeli gdzieś znajdzisz linka do zachowania o którym piszez to z chęcią poczytam
No niestety nie mogę znaleźć. Ale zrobilem eksperyment:
zalozylem tabele z jednym polem CHAR (20). No i git. Jest char
Dla pewnosci dodaje drugie pole CHAR. I jest git. Oba są CHAR.
Teraz dodaje kolejne pole, ale juz VARCHAR. No i automaycznie wszystkie pola CHAR zamieniają sie na VARCHAR. Proba ustawienia ich spowrotem na CHAR nic nie daje. Dopier gdy usune tamto VARCHAR, to moge spowrotem to zamienic na CHAR.
Nie sądze by byl to bug mojego klienta do mysql smile.gif

edit:
znalazlem w manualu biggrin.gif
http://dev.mysql.com/doc/refman/4.1/en/sil...mn-changes.html
Cytat
If any column in a table has a variable length, the entire row becomes variable-length as a result. Therefore, if a table contains any variable-length columns (VARCHAR, TEXT, or BLOB), all CHAR columns longer than three characters are changed to VARCHAR columns.
bendi
Hmm fakt - dzięki!
Wujek01
Zmieniłem typ pola hasło na varbinary(32) ale zwykły varchar z zakodowanym ciągiem znaków w md5 też uwzględnia wielości liter.
Jarod
  1. $zapytanie = "select count(*) FROM tabela WHERE nazwa=''.$name.'' and haslo=PASSWORD('$haslo')";


Ja bym to zmienił na

  1. $zapytanie = 'select count(*) FROM tabela WHERE nazwa='.$name.' and haslo=PASSWORD(''.$haslo.'')';
bendi
Cytat(Wujek01 @ 8.06.2006, 19:30 ) *
Zmieniłem typ pola hasło na varbinary(32) ale zwykły varchar z zakodowanym ciągiem znaków w md5 też uwzględnia wielości liter.

No nie calkiem - pamietasz te 3 zapytania pare postow wczesniej - przeanalizuj co one robia i zauwazysz ze jednak tak nie jest.
FiDO
Cytat(J4r0d @ 8.06.2006, 22:53 ) *
  1. $zapytanie = "select count(*) FROM tabela WHERE nazwa='$name' and haslo=PASSWORD('$haslo')";


Ja bym to zmienił na

  1. $zapytanie = 'select count(*) FROM tabela WHERE nazwa='.$name.' and haslo=PASSWORD(''.$haslo.'')';

Funkcji PASSWORD() nie powinno sie uzywac do 'celow wlasnych', jest ona przeznaczona w zasadzie na wewnetrzne potrzeby MySQL'a, jest o tym w manualu napisane.
Lepiej uzyc MD5 albo nawet SHA1 (tez jest wbudowana).
Jarod
Cytat(FiDO @ 10.06.2006, 00:10 ) *
Funkcji PASSWORD() nie powinno sie uzywac do 'celow wlasnych', jest ona przeznaczona w zasadzie na wewnetrzne potrzeby MySQL'a, jest o tym w manualu napisane.
Lepiej uzyc MD5 albo nawet SHA1 (tez jest wbudowana).


Osobiście używam SHA1. Nie poprawiałem mu tego. Chodziło mi bardziej o odzielenie łańcucha znaków od zmiennych.
SongoQ
@J4r0d No to zapomniales o
  1. \''.$name.''
Jarod
Cytat(SongoQ @ 11.06.2006, 18:54 ) *
@J4r0d No to zapomniales o
  1. \''.$name.''


Pisane szybko. Mój błąd. Poprawione
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.