Jesli kiedys bedziesz sie zajmowal wspolbieznoscia, to zorientujesz sie, ze to, co Ci napisano, to stek bzdur. Dlaczego? Bo strony internetowe sa systemami wielodostepnymi - wiele osob moze (i robi to) korzystac z nich jednoczesnie.
Skad masz pewnosc, ze miedzy sprawdzeniem, ostatniego wolnego kodu a oznaczeniem go, jako uzywany nikt inny nie sprawdzi ostatniego wolnego kodu? W ten sposob (przez krotka chwile, to prawda) dwie osoby dostana ten sam kod (bo w chwili sprawdzania dla obu byl wolny) i obie poprawia go na zajety.
Tak naprawde powinienes oznaczac kod jako uzywany, jeszcze nim go uzyjesz. Jak?
Np. zamiast flagi
used dodaj identyfikator sesji uzytkownika kodu:
CREATE TABLE IF NOT EXISTS `token` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`token` varchar(16) NOT NULL,
`used_by` varchar(32) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
I teraz - rezerwacja tokena to
najpierw update:
$query = 'UPDATE token SET used_by = "'.session_id().'" ORDER BY id DESC LIMIT 1;';
W tym momencie token jest zarezerwowany i NIKT na pewno go wiecej nie zajmie. Blokowanie ostatniego jest operacja atomowa na poziomie bazy danych, wiec nie ma mozliwosci zablokowania tego samego rekordu.
Dalej pobieramy (
tak, dopiero teraz, nie wczesniej!) ostatni zarezerwowany przez nas token (bo dawno dawno temu, ktos mogl miec taki sam identyfikator sesji).
$query = 'SELECT token FROM token WHERE used_by = "'.session_id().'" ORDER BY id DESC LIMIT 1;';
Czepiam sie, bo tylko milisekundy miedzy jednym i drugim? Moze, ale kody jednorazowe stosuje sie raczej w systemach "wysokiego" bezpieczenstwa i taka rada moze Cie uchronic przed pozniejszymi problemami. Poza tym - ucz sie dobrych nawykow.