Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> 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?
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 2)
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ę (IMG:style_emoticons/default/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
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 25.08.2025 - 13:45