Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Jak bezpiecznie zapisać do pliku?, aby zapobiec hazardowi
WebCM
post
Post #1





Grupa: Zarejestrowani
Postów: 375
Pomógł: 20
Dołączył: 28.07.2006

Ostrzeżenie: (0%)
-----


Problem jest dobrze znany przy licznikach odwiedzin, które lubią się resetować. Chcę zabezpieczyć skrypt sondy. Jest kilka plików: log.php, glosy.php... Jakich metod użyć?

Przykładowy zapis wygląda tak:
1. Odczytaj plik glosy.php za pomocą include()
2. Odczytaj plik log.php za pomocą include()
3. Zmień wartości w tablicach odczytanych z plików glosy.php i log.php
4. Zapisz plik log.php za pomocą file_put_contents() albo fwrite()
5. Zapisz plik glosy.php za pomocą file_put_contents() albo fwrite()

Hipoteza resetów liczników odwiedzin
1. Żądanie A odczytuje zawartość z pliku, zwiększa i zapisuje za pomocą file_put_contents()
2. W tym samym czasie żądanie B odczytuje zawartość pliku - być może jest wymazana
3. Żądanie B zwiększa pustą wartość i zapisze "1" do pliku

Jak się przed tym zabezpieczyć? Jest kilka sugestii:
1. Blokować dostęp zarówno do zapisu i do odczytu przy file_put_contents()
2. Sprawdzać is_writable() i is_readable() i dopiero include()
3. Po include() sprawdzić, czy istnieje tablica (która tam ma być) i nie jest pusta
4. Zapisywać do plików tymczasowych (np. glosy_new.txt), a następnie rename() do glosy.txt
5. Inny sposób - jaki jest na 100% skuteczny?

Jaki macie skuteczny sposób na hazard podczas odczytu i zapisu plików?


--------------------
„Jesteśmy różni, pochodzimy z różnych stron Polski, mamy różne zainteresowania, ale łączy nas jeden cel. Cel ten to Ojczyna, dla której chcemy żyć i pracować.” Roman Dmowski
Go to the top of the page
+Quote Post
Crozin
post
Post #2





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Samo zablokowanie pliku przy zapisywaniu uchroni Cię przed wyzerowaniem licznika, ale nie przed fałszowaniem wyników. Dwie osoby mogą odczytać plik w tym samym czasie i obie zapiszą do niego wynik o jeden większy tym samym w rezultacie otrzymasz sfałszowany wynik - ostatecznie licznik zwiększy się o 1, nie o 2.

fopen, flock (read+write), fread, fwrite, fclose - najlepiej odczyt i zapis umieścić jedno pod drugim by blokada nie wstrzymywała zbyt długo innych żądań.
Go to the top of the page
+Quote Post
WebCM
post
Post #3





Grupa: Zarejestrowani
Postów: 375
Pomógł: 20
Dołączył: 28.07.2006

Ostrzeżenie: (0%)
-----


Z doświadczenia tak nie jest. Oto kod licznika:
  1. if(file_exists('licznik.txt'))
  2. {
  3. $licznik = file_get_contents('licznik.txt');
  4. }
  5. else
  6. {
  7. $licznik = 0;
  8. }
  9. file_put_contents('./cfg/visits.txt', ++$licznik, LOCK_EX);
Działa bez zarzutów, ale skarżą się na resety. Prawdopodobnie dochodzi do hazardu.

Chcę uniknąć takich sytuacji z danymi w skrypcie, który jest oparty na plikach (logi IP, indeks sond, ilość głosów). Jeszcze nie doszło do takiej sytuacji, ale lepiej być przygotowanym na czarną godzinę smile.gif

Cytat
Samo zablokowanie pliku przy zapisywaniu uchroni Cię przed wyzerowaniem licznik
No dobrze, zablokujemy plik przy zapisie, ale nic nie stoi na przeszkodzie, aby w tym samym czasie inny wątek do odczytał. A wtedy tam nic nie będzie albo jakieś krzaczki. Nie wiem, jak zareaguje include(), bo tam będzie kod PHP, a nie liczba - wolę uniknąć fread() i eval(). Lubię używać file_put_contents() z LOCK_EX do zapisu.

A może pomysł z zapisem do pliku tymczasowego i zmiana nazwy to dobry pomysł? Nawet unikniemy fragmentacji plików - tak mi się wydaje - bo nowe dostaną tyle klastrów, ile potrzeba.

Ten post edytował WebCM 28.04.2011, 18:07:52


--------------------
„Jesteśmy różni, pochodzimy z różnych stron Polski, mamy różne zainteresowania, ale łączy nas jeden cel. Cel ten to Ojczyna, dla której chcemy żyć i pracować.” Roman Dmowski
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 22.08.2025 - 04:04