Przekazywanie sesji pomiędzy dwoma skryptami PHP poprzez plugin VLC

0

Cześć,

Mam stronkę, na której klienci mogą się logować i przeglądać swoje pliki wideo (znajdujące się na tym serwerze). Wszystko realizowane jest przez wtyczkę VLC. Mam problem ze sprawdzeniem, czy dany klient może otrzymać określony plik video, czy nie. Od strony użytkownika wygląda to tak:

$(this).closest(".recording_wrapper").find(".recording_preview").append(
    '<div class="embed_vlc_wrapper">' +
        '<embed type="application/x-vlc-plugin" pluginspage="http://www.videolan.org" version="VideoLAN.VLCPlugin.2"' +
            'version="VideoLAN.VLCPlugin.2"' +
            'target="../PHP/get_recording.php?file=' + $(this).closest(".recording_wrapper").attr("file") + '&camid=' + $(this).closest(".recording_wrapper").attr("camera_id") + '"' +
            'pluginspage="http://www.videolan.org"' +
        '/>' +
    '</div>'
);

Na tym etapie sesja już jest uruchomiona poprzez session_start(). Niestety... kiedy wywołuję tę funkcję w pliku get_recording.php, tworzy się nowa sesja - istniejąca jest ignorowana. Przez to wszystkie zmienne $_SESSION z poziomu skryptu get_recording.php są niewidoczne, bo ID sesji się nie zgadza. Na 100% nie jest to problem po stronie ustawień serwera, czy błędu w kodzie. Stronka ta jest front-endem do całego serwera streamingowego, oglądanie nagrań jest tylko jedną z podstron. Wszystkie skrypty poprawnie rozpoznają istniejącą sesję przy wywołaniu session_start() oprócz skryptu get_recording.php.
Jestem prawie pewien, że problemem jest niemożność przekazania ciastka z ID sesji do tego skryptu. Dlaczego? Ponieważ skrypt jest wywoływany przez program VLC zainstalowany na komputerze klienta, a nie skrypt z kodem który widać powyżej.
Tak więc nie za bardzo mam jak to zabezpieczyć... nie mogę zawrzeć ID sesji w URL i pobrać go przez $_GET, bo narazi mnie to np. na session hijacking. Z drugiej strony MUSZĘ jakoś przekazać ID sesji do tego skryptu przy próbie odtworzenia wideo na stronie, żeby skrypt wiedział z jakim użytkownikiem ma do czynienia i ewentualnie odmówił mu wydania pliku, jeśli nie będzie on należał do aktualnie zalogowanego użytkownika.
Myślałem o wysyłaniu ID sesji do bazy SQL i pobierania go w get_recording.php, jednak nie jest to rozwiązanie idealne i na pewno można to inaczej rozwiązać. Macie jakiś pomysł?

0

Sesje mogą być przechowywane także w ciasteczkach. Niektóre frameworki np. coś takiego mają. Takie sesje nie mają swojego unikalnego ID. To jest jeden ze sposobów, który można rozważyć. Zapisujesz więc ciasteczko a do niego całe zserializowane dane i jeszcze zaszyfrowane za pomocą albo base64encode (najprościej), albo encryptem czy coś takiego. Potem to odczytujesz.

Drugi sposób jaki mi tu przychodzi to generowanie jakiegoś losowego unqid w PHP, zapis aktualnego wygenerowanego uniqid oraz ID sesji do tabeli (MyISAM), przekazując ten uniqid (ale może być on też zhashowany np. za pomocą SHA1 czy md5) jako parametr URL do tego skrypu, który na podstawie tego wyciągnie z bazy to ID sesji. Nie wiem na ile to bezpieczne. Oczywiście i tak trzeba będzie zastosować odśmiecanie w tej tabeli, probabilistycznie tak jak to działa przy sesjach. Zamiast bazy MySQL można by pewnie rozważyć użycie Redis albo Memcached czy coś podobnego.

Napisz co o tym myślisz.

0
drorat1 napisał(a):

Sesje mogą być przechowywane także w ciasteczkach. Niektóre frameworki np. coś takiego mają. Takie sesje nie mają swojego unikalnego ID. To jest jeden ze sposobów, który można rozważyć. Zapisujesz więc ciasteczko a do niego całe zserializowane dane i jeszcze zaszyfrowane za pomocą albo base64encode (najprościej), albo encryptem czy coś takiego. Potem to odczytujesz.

Drugi sposób jaki mi tu przychodzi to generowanie jakiegoś losowego unqid w PHP, zapis aktualnego wygenerowanego uniqid oraz ID sesji do tabeli (MyISAM), przekazując ten uniqid (ale może być on też zhashowany np. za pomocą SHA1 czy md5) jako parametr URL do tego skrypu, który na podstawie tego wyciągnie z bazy to ID sesji. Nie wiem na ile to bezpieczne. Oczywiście i tak trzeba będzie zastosować odśmiecanie w tej tabeli, probabilistycznie tak jak to działa przy sesjach. Zamiast bazy MySQL można by pewnie rozważyć użycie Redis albo Memcached czy coś podobnego.

Napisz co o tym myślisz.

Dzięki za sugestię. Pomysł z szyfrowaniem mi się spodobał. Wydaje mi się, że najmniej inwazyjne rozwiązanie to (rozwinięcie Twojego):

W momencie próby uruchomienia nagrania będzie się uruchamiał inny skrypt poprzez AJAX. Jego zadaniem będzie wrzucenie obecnego ID sesji do dodatkowej kolumny w tabeli z użytkownikami (InnoDB). Nie będzie to czyste ID sesji, tylko zaszyfrowane z solą opartą na nazwie użytkownika i jego haśle. Ustawi się też Timestamp tego ID w kolejnej kolumnie w tej samej tabeli. Następnie zostanie zostanie wywołany event Play w wtyczce VLC. Nastąpi odwołanie do skryptu get_recording.php z dodatkowym parametrem - uprzednio zaszyfrowanym ID sesji. W tym skrypcie nastąpi wyszukanie tego ID w tabeli o której wcześniej wspomniałem, pobranie nazwy użytkownika, odszyfrowanie ID sesji i ustawienie jej poprzez session_id($id). Nie byłoby to bezpieczne, gdyby nie fakt, że wcześniej został ustawiony ten timestamp - skrypt zwróci nagranie TYLKO wtedy, kiedt timestamp nie będzie starszy o powiedzmy 3 sekundy od obecnej daty. Po wydaniu nagrania ID sesji zostanie wyczyszczone z bazy, a timestamp wyzerowany.

Plusy tego rozwiązania:

  • Szybkie w implementacji
  • Potencjalny hacker nie będzie mógł wykonać bezpośredniego odwołania do get_recording.php z spreparowanymi parametrami, ponieważ będzie sprawdzany wspomniany timestamp. Skrypt wyda wideo tylko wtedy, jeśli nie więcej niż 3 sekundy wcześniej zostanie uruchomiony skrypt uploadujący zaszyfrowane ID sesji do bazy SQL.
  • Teoretycznie bez znajomości hasła, nazwy użytkownika i ID sesji nie będzie możliwości otrzymania nagrania - wszystkie 3 informacje są wymagane do stworzenia hasha, który będzie sprawdzany przez get_recording.php

Minusy tego rozwiązania:

  • Jeśli z jakiegoś powodu nastąpi 'przymulenie' demona HTTP lub MySQL na serwerze, czas między wywołaniem skrypta uploadującego zaszyfrowane ID sesji do bazy, a próbą pobrania go poprzez get_recording.php będzie dłuższy od wcześniej ustalonego (3s).
0

w PHP3 nie było sesji i trzeba było je samemu napisać, i jest to proste, w bazie trzymać tylko numer sesji(całkowicie losowy), klucz ,wartość i datę wygaśnięcia po której należy rekord usunąć i tyle, opakować w prostą klasę z metodami dodającą zmienną dodaj($idsesji,$klucz, $wartosc) i pobierz($idsesji,$klucz) ew. na pewno Ktoś już to zrobił.

prawie identyczne i prostsze rozwiązanie:
baza, tabelka "bilety"/tickets
id, jakiś varchar(100) na losowy ciąg jak IDsesji
login/nick/loginid [nie wymagane], w bazie w prostej która zawiera numer
ID filmu
data wygaśnięcia [nie wymagane]
IP osoby dla której został wystawiony albo lepiej IP osoby która pierwsza z niego skorzystała

przy kliknięciu "oglądaj" jest tworzony bilet w bazie i jego ID dołączane po prostu do linku w GETcie,

ID biletu wysyłać GETem, on może i powinien być inny niż IDsesji
get_recording.php , sprawdza czy klient ma bilet po jednokrotnym użyciu biletu kasuje go z bazy, ew. wiąże go z IP jeśli (nie wiem) VLC wymaga kilku połączeń, ew. dodatkowo oprócz IP bilet ważny przez 5h od pierwszego użycia

Zalety:

  • nie ma szyfrowania .... nie można go złamać, jeden klik w oglądaj= jeden ID biletu,
    bilet nie zawierający żadnych danych (losowy identyfikator).... znaczy dla posiadacza biletu bo Ty masz wszystkie informacje o użytkowniku tego biletu w bazie ;]
  • bilet usuwany z bazy po jednokrotnym użyciu lub po danym czasie i najlepiej powiązany z danym IP

PS:
a na przyszłość jeszcze tabelka "oglądnięte" w której jest info kto, jaki film i z jakiego IP oglądał bo jeśli jeden gościu ogląda w ciągu doby 48h materiałów video z 15różnych IP to wiadomo kogo zbanować ;]

1 użytkowników online, w tym zalogowanych: 0, gości: 1