Skocz do zawartości

Logowanie i pobieranie danych z serwera [Bazy Danych]


oLuju

Rekomendowane odpowiedzi

Większość problemów w mojej multiplayer'owej grze mam już za sobą. Postanowiłem teraz zaimplementować system odpowiedzialny za logowanie się na serwery gry a następnie pobieranie danych odnośnie danego gracza. Udało mi się to i działa bez najmniejszego zarzutu i teraz pewnie ktoś zada pytanie po co w takim razie o tym pisze, otóż z tego co wiem to sposób w jaki to zrobiłem nie należy do najbezpieczniejszych. Chciałbym poradzić się czy jednak to wystarczy a jak nie to jakie zabezpieczenia można byłoby dodać.

Skrypt wygląda tak:

Create:

login = get_string("Podaj login:", "login");
password = get_string("Podaj haslo:", "password");

get = http_get("http://mojastrona.pl/logon.php?login=" + login + "&password=" + password + "&alrd_logged=1");

Async Event - HTTP:

///Czekanie na odebranie danych

{
if ds_map_find_value(async_load, "id") == get
   {
   if ds_map_find_value(async_load, "status") == 0
      {
      r_str = ds_map_find_value(async_load, "result");
      alarm[0]=5
      }
   else
      {
      r_str = "null";
      }
   }
}

Alarm 0:

///Odczytywanie odebranych danych z Bazy Danych (DataBase)

if string_pos("Login: ", r_str) != 0
   {
   login = string_copy(r_str, string_pos("Login: ", r_str)+7, ((string_pos("LOGIN_END", r_str))-(string_pos("Login: ", r_str))-7) );
   //string_insert(name, text, string_pos(",", text));
   }
if string_pos("alrd_logged: ", r_str) != 0
   {
   alrd_logged = string_digits(string_copy(r_str, string_pos("alrd_logged: ", r_str)+13, ((string_pos("ALRD_LOGGED_END", r_str))-(string_pos("alrd_logged: ", r_str))-13) ));
    if ( alrd_logged == "1" )
        {
        imowner = 0
        show_message("Uzytkownik aktualnie zalogowany!")
        game_restart()
        exit;
        }
    else
        {
        imowner = 1
        }
   }
if string_pos("Rank: ", r_str) != 0
   {
   rank = string_copy(r_str, string_pos("Rank: ", r_str)+6, ((string_pos("RANK_END", r_str))-(string_pos("Rank: ", r_str))-6) );
   //string_insert(name, text, string_pos(",", text));
   }

Wytłumaczę teraz trochę jak to działa. W Creat'ie prosi się użytkownika o wpisanie Loginu i Hasła, a następnie to jest wysyłane na stronę gdzie odbywa się weryfikacja i wysłanie danych. Odpowiednie dane odczytywane są z bazy i wyświetlane w takiej postaci:

Logowanie udane!
Login: Gracz1LOGIN_END
[...]

Gdy dane dojdą skrypt w Alarmie zajmuje się znalezieniem odpowiednich wartości i zapisaniu ich w zmiennych. Niestety korzystam z darmowego hostingu na którym są reklamy, a ich kod html znajduje się w Result'ie. Wiem, że można użyć JSON'a bo sam GM ma do tego specjalne komendy i jest to prostsze ale chyba tylko w przypadku gdy result zawiera wyłącznie kawałek tego JSON'a (bez śmieci takich jak reklamy). Kod szuka pozycji startowej danej wartości np.: loginu, potem szuka końca który oznaczony jest napisem: "COSTAM_END" i wyznacza pozycje którą ma skopiować do zmiennej.

Teraz co to jest "alrd_logged" - zmienna, która mówi o tym czy użytkownik jest aktualnie zalogowany (korzysta ze swojego konta). Na początku podczas logowania na stronę wysyłana jest zmienna alrd_logged=1 że gracz się loguje i jeśli w result'ie "alrd_logged" z bazy danych ma już wartość 1 traktujemy to tak że ktoś już korzysta z konta i nie można się do niego zalogować. Gdy wyłączymy grę jest taki kod:

(Game end) i (Press 'Escape'):

///Wyloguj mnie

if ( imowner == 1 )
    {
    show_message("Wylogowywuje sie...")
    http_get("http://mojastrona.pl/logon.php?login=" + login + "&password=" + password + "&alrd_logged=0");
    show_message("Pomyslnie wylogowano!!!")
    }
else
    {
    //probowalem zalogowac sie na czyjesc konto
    }

imowner to zmienna pomocnicza która jest równa 1 jeśli pomyślnie zalogowaliśmy się na konto - jest to zabezpieczenie przed tym by w momencie gdy "włamywacz" zna passy do konta prawdziwego właściciela to w momencie wyjścia z gry ta nie wysłała informacji o wylogowanie się (nie ustawiła alrd_logged na 0 - tak jakby nikt nie był zalogowany).

Sama strona internetowa (logon.php) czyta GET'a tak:

1.Sprawdzanie poprawności loginu i hasła - czy istnieją w bazie danych

2.Jeśli tak wysyłanie informacji o użytkowniku

3.Jeśli strona otrzyma alrd_logged=1 tak też ustawi w bazie danych (a jeśli 0 to analogicznie ustali 0 w bazie danych).

Są 2 "dziury":

1.Potencjalny włamywacz odbiera zawsze w result'ie wszystkie dane o użytkowniku, tylko że alarm na samym starcie przed "przesianiem i posegregowaniem" zmiennych z tego co przyszło sprawdza alrd_logged z strony i jak jest 0 to kontynuuje, a jak nie (czyli 1) to zatrzymuje się, wywala komunikat o tym że ktoś już korzysta z konta i restartuje grę (na razie w ramach testu, oczywiście).

2. Przy próbie logowania na server wysyłamy zmienną alrd_logged=1 a co za tym idzie ponownie ustalamy ją na 1 w samej bazie danych. W przypadku jak ktoś już korzysta z konta nie wprowadza to tak naprawdę żadnej zmiany.

Te 2 niedociągnięcia nie wydają mi się jakoś zbyt niebezpieczne więc ich nie poprawiałem, jednak problem leży w samym request'ie (żądaniu) wysyłanym na stronę, gdyż nasz Login i Hasło idzie zupełnie "gołe" , a nie zabezpieczone (zahashowane lub inaczej zaszyfrowane [jednak nie mam pojęcia jak by to zrobić]).

 

Macie jakieś pomysły co zmienić, ulepszyć bądź dodać???

Odnośnik do komentarza
Udostępnij na innych stronach

Pomijająć brak szyfrowania, skorzystalbym z funkcji http_request aby wysłać POST z hasłem w body zamiast korzystać z GET.

Gnysek pewnie zaraz wejdzie i poda jeszcze lepsze rozwiązanie.

Edit:

Ogólnie idea zalogowania i wylogowania jest tutaj absolutnie zbędna. Te rzeczy istnieją w przeglądarkach aby wyświetlać dostęp do konkretnego contentu, z poziomu gry możesz operować samym UserID, Hasłem i może kluczem sesji jak już musisz.

Odnośnik do komentarza
Udostępnij na innych stronach

Ta wiem, że z tym szyfrowaniem lipton straszny i to jest niezbędne. Co do http_requesta to widziałem że ten pozwala na użycie POST'a ale widząc przykład w dokumentacji trochę mi się to odwidziało, ale będę musiał tego spróbować.

8 minut temu, I am vader napisał:

Ogólnie idea zalogowania i wylogowania jest tutaj absolutnie zbędna

No ale bez tej funkcji z 1 konta jest w stanie korzystać niezliczona ilość osób. Co innego gdyby baza danych była w stanie załóżmy po 10 minutach automatycznie "wylogować" gracza jeśli ten nie pobiera/wysyła żadnych danych (coś w rodzaju timeout'a).

Generalnie próbowałem szukać sposobu by działało to tak ja w przeglądarce, czyli np.: w sesjach. Gracz loguje się, jest połączony z bazą danych (jest w stanie odczytywać/zapisywać w niej dane [oczywiście tylko w obrębie swojego profilu/konta]), może się wylogować albo jeśli przez pewien czas nie będzie nic robił (idle) automatycznie go lognie (timeout).

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Timeout jest prosty - zapisujesz o której godzinie gracz ostatni raz aktualizował sesję, a przy logowaniu robisz

$time = time() - 600; // 10 minut

$sql = "DELETE * FROM session WHERE last_time < {$time}";

W czasie, gdy nikt nie korzysta ze strony i tak nie ma znaczenia, że sesja nie jest skasowana, bo nikt nie czyta też bazy :)

 

Czy ten hosting dokleja reklamy również jak zrobisz:

<?php
header('Content-type: application/json');
echo json_encode(array('logged_in' => true));

 

Btw. ogólnie są małe hostingi za grosze dzisiaj (5zł miesięcznie) - więc może pomyśl nad tym? Np. tutaj https://www.webd.pl/ masz za 4 złote. Albo na https://az.pl/hosting/ masz za 15 zł rocznie (tylko poczytaj regulamin, czy to nie promocja a za rok 5x tyle skasują, aczkolwiek ja płacę 100 zł rocznie za dużo większe hostingi).

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...