Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [klasa] Zabezpieczenie obrazków
Forum PHP.pl > Inne > Oceny
Fifi209
Witam, ostatnimi czasy pojawia się dużo tematów jak zabezpieczyć obrazki (np. tylko dla domeny, tylko dla zalogowanych etc.)

(edit)
Stara wersja: http://www.wklej.eu/index.php?id=0382f95e6b
Nowa wersja:
(w kolejnym poście jest wersja z inną obsługą wyjątków)
  1. interface iSecurity {
  2. public function read($file);
  3. public function setExtensions($array);
  4. public function ExtensionsInfo();
  5. // protected function write();
  6. }
  7.  
  8. class Security implements iSecurity {
  9.  
  10. private $extensions = array(
  11. 'jpg' => 'image/jpeg',
  12. 'jpeg' => 'image/jpeg',
  13. 'png' => 'image/png',
  14. 'gif' => 'image/gif',
  15. 'bmp' => 'image/bmp'
  16. );
  17.  
  18. private $path;
  19. private $file;
  20.  
  21. public function read($file) {
  22. $path_info = pathinfo($file);
  23. if (array_key_exists($path_info['extension'], $this->extensions)) {
  24. $this->path = $path_info['dirname'];
  25. $this->file = array('filename' => $path_info['filename'], 'extension' => $path_info['extension']);
  26. $this->write();
  27. }else{
  28. throw new Exception('Plik z tym rozszerzeniem nie są obsługiwane.');
  29. }
  30. }
  31.  
  32. public function setExtensions($array) {
  33. $this->extensions = $array;
  34. }
  35.  
  36. public function ExtensionsInfo() {
  37. return $this->extensions;
  38. }
  39.  
  40. private function write() {
  41. $temp = $this->path.'/'.$this->file['filename'].'.'.$this->file['extension'];
  42. if (file_exists($temp)) {
  43. header('Content-Type: '.$this->extensions[$this->file['extension']]);
  44. readfile($temp);
  45. }else{
  46. throw new Exception('Plik nie może zostać odczytany.');
  47. }
  48. }
  49.  
  50. }


Przykład użycia:
  1. try {
  2. $test = new Security;
  3. $test->read('img01.png');
  4. }catch(Exception $e) {
  5. echo $e->getMessage();
  6. }


Wystarczy dodać warunek np. czy użytkownik jest zalogowany i po sprawie. winksmiley.jpg
marcio
Nie ma zabardzo co oceniac bo malo jednak lepsze byloby tak jak mowisz pole publiczne ktore mozna ustawic za pomoca settera i odrazu poprzez dostep do niego z zewnatrz klasy bedzie bardziej przejrzyscie.



Mi przypadl do gustu bardziej wzorzec strategia jest on bardziej taki lopatologiczny i lepiej on wyglada, i tak jak mowisz nie pakuj wszystkiego do jednej klasy tylko zrob klase glowna ktora bedzie implementowala kod podklas.

Fifi209
Tutaj wersja z własną obsługą wyjątków + przykład:
  1. <?php
  2.  
  3. class SecurityException extends Exception {
  4.  
  5. public function asImage() {
  6. $width = strlen($this->getMessage()) * 6.9 + 30;
  7. $img = imagecreatetruecolor($width, 50);
  8. $white = imagecolorallocate($img, 255, 255, 255);
  9. $black = imagecolorallocate($img, 0, 0, 0);
  10. imagefilledrectangle($img, 0, 0, $width, 50, $black);
  11. imagestring($img, 3, 15, 18, $this->getMessage(), $white);
  12. header('Content-Type: image/png');
  13. imagepng($img);
  14. imagedestroy($img);
  15. }
  16.  
  17. }
  18.  
  19. interface iSecurity {
  20. public function read($file);
  21. public function setExtensions($array);
  22. public function ExtensionsInfo();
  23. // protected function write();
  24. }
  25.  
  26. class Security implements iSecurity {
  27.  
  28. private $extensions = array(
  29. 'jpg' => 'image/jpeg',
  30. 'jpeg' => 'image/jpeg',
  31. 'png' => 'image/png',
  32. 'gif' => 'image/gif',
  33. 'bmp' => 'image/bmp'
  34. );
  35.  
  36. private $path;
  37. private $file;
  38.  
  39. public function read($file) {
  40. $path_info = pathinfo($file);
  41. if (array_key_exists($path_info['extension'], $this->extensions)) {
  42. $this->path = $path_info['dirname'];
  43. $this->file = array('filename' => $path_info['filename'], 'extension' => $path_info['extension']);
  44. $this->write();
  45. }else{
  46. throw new SecurityException('A file with this extension is not supported.');
  47. }
  48. }
  49.  
  50. public function setExtensions($array) {
  51. $this->extensions = $array;
  52. }
  53.  
  54. public function ExtensionsInfo() {
  55. return $this->extensions;
  56. }
  57.  
  58. private function write() {
  59. $temp = $this->path.'/'.$this->file['filename'].'.'.$this->file['extension'];
  60. if (file_exists($temp)) {
  61. header('Content-Type: '.$this->extensions[$this->file['extension']]);
  62. readfile($temp);
  63. }else{
  64. throw new SecurityException('The file does not exist.');
  65. }
  66. }
  67.  
  68. }
  69.  
  70. try {
  71. $test = new Security();
  72. $test->read('img01.jpg');
  73. }catch(SecurityException $e) {
  74. echo $e->asImage();
  75. }
  76.  
  77.  
  78. ?>


Lepsza wersja z własną obsługą wyjątków czy poprzednia?
wookieb
Toż to zwykły force - download w dodatku niedopracowany smile.gif
Fifi209
Cytat(wookieb @ 17.08.2009, 16:31:31 ) *
Toż to zwykły force - download w dodatku niedopracowany smile.gif

Czy ja wiem czy taki force - download. To że niedopracowany to wiadomo, czekam na sugestie a potem coś takiego z przykładami dam do gotowych rozwiązań. (dla laików)
viking
O, dzisiaj podobne bzdury pisałem winksmiley.jpg Dodatkowo sprawdzam czy rozszerzenie zgadza się z mime.
Orientujecie się czy getimagesize() może coś dziwnego zwrócić co nie spełni warunku:
  1. if(!getimagesize($filename)){ throw new...}

?
NuLL
A do czego jest ten interfejs i czemu on sluzy ?
Fifi209
Cytat(NuLL @ 17.08.2009, 19:30:26 ) *
A do czego jest ten interfejs i czemu on sluzy ?

Chciałem dodać obsługę dokumentów, nie wiem sam czemu. smile.gif Ale właściwie nie zaszkodzi niczemu ten interfejs.
phpion
No tylko że taki interfejs nie wnosi nic poza tym, że pokazuje że coś Ci tam świta o interfejsach ale za bardzo nie wiesz jak i kiedy je stosować. Do tego ta nazwa kompletnie z kosmosu; poza tym nie trzyma się kanonu *able. Według mnie logiczniej byłoby podzielić interfejs na 2 osobne:
  1. interface Extendable {
  2. public function setExtensions(array $array);
  3. public function ExtensionsInfo();
  4. }
  5.  
  6. interface Readable {
  7. public function read($resource);
  8.  
  9. }
zegarek84
Cytat(fifi209 @ 17.08.2009, 16:05:05 ) *
Witam, ostatnimi czasy pojawia się dużo tematów jak zabezpieczyć obrazki (np. tylko dla domeny, tylko dla zalogowanych etc.)
[....]
Wystarczy dodać warunek np. czy użytkownik jest zalogowany i po sprawie. winksmiley.jpg

ekchmmm...

sorki - może żle zrozumiałem ten temat i może wyjdzie mały oftopick ale... cytuj co zacytowałem to wg. mnie pasowało by w pierwszej kolejności pokazać "wejście/przekierowanie" z adresu obrazka na właściwy skrypt *.php - np. w .htaccess:
Kod
RewriteRule ^(.+\.(?:gif|jpeg|jpe|jpg|png|bmp))$ /curl/img_buforuj.php?co=$1 [L]


i dopiero w skrypciku zrobić co się chce - chyba że akurat Twoje skrypty mają mieć rozszerzenie *.php?? - ale jakby nie było skądś pasuje mieć te dane o rozszerzeniu - czyli jakieś wspomnienie z powiązaniem z bazą danych - choćby z "płaską" bazą danych...

sorki - po kilku piwkach tera może dziwnie piszę ale będąc już w skrypcie php wystarczy sprawdzić co się chce na początku i zwrócić przez return co się chce lub wykonać exit - i nie wiem jak skomplikowane musiało by być zabezpieczenie (no przy własnych sesjach na obiektach ale...) normalnie to raczej procedury jako zabezpieczenie (tylko to co z bazą powiązane jako obiekt)... no i jeśli struktura obrazków połączona z bazą to obiekt - ale ten szkielet co widzę to raczej mi przypomina bardziej weryfikację wgrywanych obrazków na serwer przez własne api...
Fifi209
Cytat(phpion @ 17.08.2009, 20:52:48 ) *
No tylko że taki interfejs nie wnosi nic poza tym, że pokazuje że coś Ci tam świta o interfejsach ale za bardzo nie wiesz jak i kiedy je stosować. Do tego ta nazwa kompletnie z kosmosu; poza tym nie trzyma się kanonu *able. Według mnie logiczniej byłoby podzielić interfejs na 2 osobne:

JAK JUŻ WSPOMNIAŁEM, interfejs miał być implementowany do DWÓCH klas tak więc został zastosowany. A o tym, że to jest bez sensu (z założeń jakie były na początku przy tworzeniu kodu) tak więc nie napisałem drugiej klasy.

Cytat(zegarek84 @ 17.08.2009, 21:48:44 ) *
ekchmmm...

...mmmhcke ;/

Cytat(zegarek84 @ 17.08.2009, 21:48:44 ) *
sorki - może żle zrozumiałem ten temat i może wyjdzie mały oftopick ale... cytuj co zacytowałem to wg. mnie pasowało by w pierwszej kolejności pokazać "wejście/przekierowanie" z adresu obrazka na właściwy skrypt *.php - np. w .htaccess:
Kod
RewriteRule ^(.+\.(?:gif|jpeg|jpe|jpg|png|bmp))$ /curl/img_buforuj.php?co=$1 [L]

Bardziej chodzi o sytuację kiedy:
  1. if ($_SESSION['login'] === true) {
  2. try {
  3. $test = new Security;
  4. $test->read('image.png');
  5. }catch(SecurityException $e) {
  6. echo $e->asImage();
  7. }
  8. }else{
  9. // niezalogowany
  10. }

Mam nadzieję, że rozumiesz. Obrazek tylko dla zalogowanych. winksmiley.jpg

Cytat(zegarek84 @ 17.08.2009, 21:48:44 ) *
i dopiero w skrypciku zrobić co się chce - chyba że akurat Twoje skrypty mają mieć rozszerzenie *.php?? - ale jakby nie było skądś pasuje mieć te dane o rozszerzeniu - czyli jakieś wspomnienie z powiązaniem z bazą danych - choćby z "płaską" bazą danych...

Tego w ogóle nie rozumiem.

Cytat(zegarek84 @ 17.08.2009, 21:48:44 ) *
sorki - po kilku piwkach tera może dziwnie piszę

To akurat rozumiem, normalna sprawa. Ale nie musisz się chwalić doznaniami z wakacji.


Cytat(zegarek84 @ 17.08.2009, 21:48:44 ) *
ale będąc już w skrypcie php wystarczy sprawdzić co się chce na początku i zwrócić przez return co się chce lub wykonać exit - i nie wiem jak skomplikowane musiało by być zabezpieczenie (no przy własnych sesjach na obiektach ale...) normalnie to raczej procedury jako zabezpieczenie (tylko to co z bazą powiązane jako obiekt)... no i jeśli struktura obrazków połączona z bazą to obiekt - ale ten szkielet co widzę to raczej mi przypomina bardziej weryfikację wgrywanych obrazków na serwer przez własne api...

Jaką weryfikację? On odczytuje obrazek z serwera, wysyła nagłówek i potem obrazek. (albo źle Cię zrozumiałem)
zegarek84
Cytat(fifi209 @ 17.08.2009, 23:10:43 ) *
Mam nadzieję, że rozumiesz. Obrazek tylko dla zalogowanych. winksmiley.jpg

właśnie o coś takiego mi chodziło - lub na hotlink... ale nie było sprecyzowane tongue.gif
Cytat(fifi209 @ 17.08.2009, 23:10:43 ) *
Tego w ogóle nie rozumiem.

sorki ale już z Security->read($file) musisz jakoś przekierować zmienną $read ;p - wiem jest na to kilka sposobów - ale jak na temat nie wskazałeś żadnego tongue.gif
Cytat(fifi209 @ 17.08.2009, 23:10:43 ) *
To akurat rozumiem, normalna sprawa. Ale nie musisz się chwalić doznaniami z wakacji.
Sorki - Ty jesteś dłużej na forum to akurat wiesz, że nie piszę, żeby sobie posty nabijać tongue.gif
Cytat(fifi209 @ 17.08.2009, 23:10:43 ) *
Jaką weryfikację? On odczytuje obrazek z serwera, wysyła nagłówek i potem obrazek. (albo źle Cię zrozumiałem)

no może nie do końca ale trzymając się tematu:
Cytat(fifi209)
[klasa] Zabezpieczenie obrazków

to jeśli odczyt to jakaś weryfikacja danych wejściowych czy ten użytkownik tongue.gif...
a jeśli wgrywanie plików to raczej czy plik poprawny i czy ten user może wgrać ^^...

sorku za takie komentarze gdyż treściwie piszesz - ale jakby nie było forum jest do wymiany poglądów tongue.gif
Fifi209
Cytat(zegarek84 @ 18.08.2009, 00:32:38 ) *
właśnie o coś takiego mi chodziło - lub na hotlink... ale nie było sprecyzowane tongue.gif

Dobrze, że się dogadaliśmy.

Cytat(zegarek84 @ 18.08.2009, 00:32:38 ) *
sorki ale już z Security->read($file) musisz jakoś przekierować zmienną $read ;p - wiem jest na to kilka sposobów - ale jak na temat nie wskazałeś żadnego tongue.gif

Nie rozumiem w czym problem dalej? Zmienna $read? Co mam przekierowywać? smile.gif
Cytat(zegarek84 @ 18.08.2009, 00:32:38 ) *
Sorki - Ty jesteś dłużej na forum to akurat wiesz, że nie piszę, żeby sobie posty nabijać tongue.gif

Nie zwracam zbytnio uwagi na to kto nabija a kto nie, ale chyba w hydepark i w ocenach licznik jest wyłączony.
Cytat(zegarek84 @ 18.08.2009, 00:32:38 ) *
to jeśli odczyt to jakaś weryfikacja danych wejściowych czy ten użytkownik tongue.gif...

To już pozostawiam programistom, może chodzi o to czy ktoś jest zalogowany, czy ktoś ma x postów na forum, czy ma uprawnienia - nie wiem, jak pozostawię tak jak jest to będzie uniwersalnie. (jeżeli nie rozumiesz to mogę później napisać przykład)
Cytat(zegarek84 @ 18.08.2009, 00:32:38 ) *
a jeśli wgrywanie plików to raczej czy plik poprawny i czy ten user może wgrać ^^...

O wgrywaniu w ogólnie nie było mowy.
Cytat(zegarek84 @ 18.08.2009, 00:32:38 ) *
sorku za takie komentarze gdyż treściwie piszesz - ale jakby nie było forum jest do wymiany poglądów tongue.gif

No do tego służy forum właśnie. A temat powstał po to abym dostał kilka uwag co do kodu.
Fafu
Hmm, a jaka jest różnica między twoim skryptem na tym? biggrin.gif
  1. <?php
  2. if($zalogowany) {
  3. echo '<img src="obrazek.jpg">';
  4. }
  5. ?>
zegarek84
BARDZO DUŻA
jeśli ktoś się zaloguje w Twoim przypadku i skopiuje adres obrazka i puści to w sieć to ten obrazek jest dostępny dla wszystkich - nie jest w żaden sposób zabezpieczony (a przed czym czy hot linkiem czy zalogowany - w sumie czy zalogowany to i hotlinkować się nie będzie dało ^^) to decyzja programisty....

jednak właśnie dlatego były moje posty gdyż co niektórzy mogli tej różnicy nie widzieć - po to też np. napisałem linijkę z .htaccess by adresy wyglądające jak obrazek były adresami do skryptów php z przekazaniem parametru jaki miał się obrazek wyświetlić - a dopiero skrypt php analizuje czy może się wyświetlić czy nie - skrypt wysyła odpowiednie nagłówki dla przeglądarki a następnie postać binarną pliku...

pisząc o tych "przekierowaniach" lub dopytując się jak to tutaj wygląda chciałem by to było bardziej zrozumiałe dla wszystkich - no w końcu skądś wartość danych zmiennych do analizy musi się brać...

...nic nie stoi na przeszkodzie żeby obrazki wszystkie miały rozszerzenie *.php - jednak naturalniej wygląda jeśli obrazki mają "swoje" rozszerzenie - regułka w .htaccess może być inna niż przedstawiłem wyżej i już można analizować trochu inaczej ale jaka by nie było ta linijka powoduje, że obrazki w kodzie strony wyglądają "normalnie"
viking
Cytat(zegarek84 @ 18.08.2009, 10:43:37 ) *
...nic nie stoi na przeszkodzie żeby obrazki wszystkie miały rozszerzenie *.php

Tak. I jeszcze wrzucić do katalogu wykonywalnego. Raj dla włamywacza.
zegarek84
ależ Wy mnie tu nie rozumiecie ;p - same obrazki NIE MOGĄ mieć rozszerzenia *.php!!! - ale żeby było zabezpieczenie jakieś to musisz w kodzie html'a podać adres gdzieś - i jeśli nie znasz .htaccess'a to podajesz do jakiegoś pliku *.php z jakimiś parametrami i w tym pliku decydujesz czy wyświetlić dane czy nie... a jeśli znasz .htaccess to robisz przekierowanie do pliku *.php i tam decydujesz...

no w końcu w kodzie html naturalniej wygląda adres:
<img src="obrazek_smiech.jpg" /> niż np.: <img src="obrazki.php?src=obrazek_smiech&typ=1" /> gdzie typ 1 to np. jpg...

i właśnie ten pierwszy post w temacie i jego ideę moim zdaniem nie wszyscy zrozumieli co potwierdzają dzisiejsze posty ;p
Fifi209
To może ja się wypowiem.
Kiedy i gdzie można to zabezpieczenie stosować. Wyobraźmy sobie, iż mamy portal gdzie użytkownicy dają swoje zdjęcia, jak np. Nasza-Klasa.pl gdzie profile i zdjęcia są dostępne tylko dla zalogowanych (przynajmniej teoretycznie w tym wypadku).

A więc mamy jakiś tam formularz do logowania i do zmiennej:
  1. $_SESSION['login'] = true;

przypisujemy wartość TRUE gdy użytkownik podał prawidłowe dane.

Użytkownik przechodzi do galerii i na początku kodu programista daje:
  1. if ($_SESSION['login'] == true) {
  2.  
  3. // kod
  4.  
  5. }else{
  6.  
  7. // informacja że musisz się zalogować
  8.  
  9. }


W miejsce kodu wpisujemy np. :
  1. try {
  2. $test = new Security;
  3. $test->read('user/obrazek.jpg');
  4. }catch(SecurityException $e) {
  5. $e->asImage();
  6. }

I zalogowany użytkownik dostanie obrazek.jpg smile.gif Wystarczy teraz wpiąć to np. w pętlę i jest. (np. dane o obrazkach użytkownika pobieramy po loginie [według folderów])
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-2024 Invision Power Services, Inc.