Unity3d QuickTip – czyli szybkie porady, rozwiązania częstych problemów i sztuczki w Unity3d!

Dzisiejszy odcinek: Komunikacja z serwerem www

Uwaga! Jest to poradnik typu QuickTip. Zatem skupia się on na osiągnięciu założonego celu. Zatem zakładamy że użytkownik zna na tyle program Unity3d, aby samodzielnie wykonać najprostsze czynności, jak np. dodanie modelu kostki do sceny czy dodanie modelowi jakiegoś komponentu. Jeżeli brakuje Ci tej podstawowej wiedzy, zapraszam do tutoriala:
Unity Tutorial – Podstawy

Teoria

Zapewne każdy kojarzy takie rzeczy jak opcja logowania w grze, czy lista rankingowa najlepszych graczy. Takie coś najczęściej tworzone są przez komunikację klienta gry z zewnętrznym serwerem www.  Kiedy wchodzimy na listę rankingową, nasz klient odpytuje serwer, który pobiera wyniki z bazy danych i przesyła je ponownie do klienta. Całość odbywa się po protokole HTTP, czyli tak jak ma to miejsce w przypadku przeglądania stron w przeglądarce.

Komunikacja klient - serwer
Komunikacja klient – serwer

Jeśli chodzi o klienta, sprawa jest prosta. Mamy tutaj nasze Unity ze starym dobrym C#. Klient z serwerem komunikuje się za pomocą protokołu HTTP, wykorzystując API.
[stextbox id=”info” defcaption=”true”]API (Application Programming Interface) – Czyli zestaw ściśle określonych reguł, informujących jak dane programy mają się ze sobą komunikować. Zasadniczo sprowadza się do tego, że w sytuacji kiedy jedna aplikacja, chce coś od drugiej, musi znać tylko komendy API.

W naszym przypadku klient Unity, nie musi wiedzieć jaka jest baza danych, jak się nazywają tabele w bazie danych, czy kolumny w tabelach, nie musi wiedzieć czy serwer stoi na Linuxie, Unixie czy Windowsie. Czy interfejs został napisany w PHP, ASP czy Ruby. Nie potrzebuje wiedzy na czym stoi baza danych. Musi znać tylko polecenia API, co bardzo ułatwia samą komunikację.

Do tego klienty, napisane na różne sposoby mogą korzystać z tego samego API. Co oznacza, że ten sam serwer może odpytać klient gry, ale też osoba korzystająca z przeglądarki internetowej, ciekawa jak jej idzie w rankingu.[/stextbox]
Kluczową do napisania przez nas rzeczą, będzie właśnie API na poziomie serwera, aby umożliwić klientom łatwe odpytywanie go. Dzięki wykorzystaniu API, nie musimy znać specyfiki serwera – więcej w ramce powyżej.

Serwer w naszym przypadku będzie po prostu stroną www, bez interfejsu, która będzie odpowiadać na żądania klientów. Taka typowa strona internetowa może powstać w PHP, ASP.NET, Ruby, Pythonie, JavaScriptci i masie innych języków. My wykorzystamy PHP.

Przechodzimy do ostatniego elementu, czyli magazynu danych, jakim jest baza danych. Tam trzymamy wszelkie informacje. Znów typów oprogramowania bazodanowego jest wiele. MySQL, PostgreSQL, Oracle i naprawdę masa innych. Tutaj my znów uśmiechniemy się do MySQL.

Plan

Projekt jest nieco większy niż dotychczasowe tutoriale, dlatego musimy sobie ułożyć prosty plan.

  1. Pierwsza część – czyli to co teraz czytasz – opowie jak przygotować bazę danych i stworzyć samo API, oraz testowego klienta w przeglądarce.
  2. Druga część, zajmie się przygotowaniem klienta w Unity.
  3. W ostatniej części zajmiemy się kwestią zabezpieczeń. Dane, szczególnie newralgiczne jak hasło, e-mail, dane personalne etc. nie mogą latać po sieci samopas.

Tutaj od razu informacja dla kodowych purystów: zabezpieczenie będzie w 3 części. Nie dodaje go od razu w celu edukacyjnym – żeby nie komplikować od razu samego PHP i MySQL, które dla większości może być czymś całkiem nowym.

Będę starał się przybliżyć podstawy PHP i MySQL, ale nie będzie to zbyt kompletny kurs, więc zainteresowanych odsyłam do kursów internetowych. Chyba, że będzie zainteresowanie, to dajcie znać, a mogę przygotować kurs tego języka.

Przygotowanie

Pierwszą rzeczą jaką będzie trzeba zrobić to zdobyć jakiś serwer z bazą danych. Na potrzeby profesjonalnej gry, takie coś raczej się kupuje i opłaca. Na potrzeby nauki, wystarczy nam jakiś prosty darmowy hosting. Gdzie takie coś można dostać? W wielu miejscach:

  • http://www.hostinger.pl/zamow
  • https://www.cba.pl/panel/pl/register/hosting/free
  • Wiele innych stron

Wierzę, że w dzisiejszych czasach, każdy jest w stanie pokonać kilka pól w formularzu, więc nie będę się tutaj produkował jak założyć konto. Po założeniu konta, kluczowe będą dwie informację:

  • Dane dostępowe do konta FTP.
  • Dane dostępowe do bazy danych.

Te sobie gdzieś zapiszcie i przechodzimy do dalszej pracy. Jak by kogoś to interesowało, ja będę pracował na swoim serwerze, na którym stoi blog.
[stextbox id=”info” defcaption=”true”]Istnieje możliwość pracy na serwerze lokalnym (localhost), aby go stworzyć u siebie na komputerze, wystarczy zainstalować program WAMP, który jest kompletnym pakietem. Jednak są dwie wady takiego rozwiązania: Serwer działa, do póki program jest włączony. Jeśli nie dysponujesz zewnętrznym adresem IP, to mogą być problemy z połączeniem się z serwerem z innego komputera.[/stextbox]

Baza danych

Stworzymy system logowania i rejestracji – są nieco bardziej skomplikowane od listy rankingowej, więc będą lepszym przykładem.

Pierwszy krok to przygotowanie bazy danych. W bazie danych mamy do czynienia z tabelami. To w nich przechowujemy rekordy – czyli kolejne wpisy. Tabela charakteryzowana jest przez kolumny, czyli dostępne pola.

Przykładowa tabela w bazie danych MySQL
Przykładowa tabela w bazie danych MySQL

Na powyższym przykładzie mamy standardową tabelę WordPressa – przykład z mojej lokalnej strony testowej, więc nie ma co próbować włamu.

Kolumny to: ID, user_login, user_pass etc. Co jest ważne? Nazwy powinny składać się z małych liter, podkreślenia i opisywać co w danej kolumnie znajdziemy.

Kolejne rekordy chyba są oczywiste.

Jednak to nie wszystko czym tabela jest opisana. Każda kolumna, ma swoją specyfikę – strukturę.

Struktura tabeli wp_users
Struktura tabeli wp_users

Powyżej widzimy tą samą tabelę co na poprzednim obrazku, ale tym razem widzimy jej specyfikę. Każda kolumna ma swoją nazwę, typ (varchar to string, int to int, datetime to format daty), formatów jest sporo i nie będę wszystkich omawiał. Metoda porównywania napisów to styl kodowania tekstów. Przykładowo Windows wykorzystuje stronę kodowania Windows-1250, obecnie najpopularniejsze kodowanie to UTF, czyli Unicode – z niego zalecam korzystać w każdej internetowej kwestii. Kolejna rzecz to atrybuty, takim przykładowym jest unsinged – czyli bez znaku. Co to daje? W klasycznym zapisie bitowym mamy bit znaku – czy liczba jest dodatnia czy ujemna. Przez to zmniejsza się liczba bitów do wykorzystania na liczbę. Jednak jeśli mamy pewność, że dana zmienna nie przyjmie wartości ujemnej, to możemy wykorzystać unsigned i dodatkowy bit przeznaczyć również na liczbę zwiększając jej maksymalny dodatni zakres.

Kolumna Null, określa czy pole może być Null-em, czyli nie mieć wartości. Wartość domyślna jest oczywista – jak nie podamy wartości jawnie w zapytaniu, to zostanie ustawiona wartość domyślna. Dodatkowo – to różne parametry, widoczne Auto_increment, automatycznie zwiększa wartość dla pola ID. Więc jeśli jawnie nie wymusimy innej wartości, to pole ID dostanie wartość o 1 większą od ostatniego wpisu.

Przejdźmy do budowania samej tabeli.

Gdzieś w panelu administracyjnym hostingu powinien być link do czegoś, o magicznej nazwie phpMyAdmin. Klikamy w to i logujemy się danymi dostępowymi do bazy danych. Waszym oczom powinno ukazać się coś takiego:

Wygląd panelu phpMyAdmin
Wygląd panelu phpMyAdmin

Ponownie konto lokalne – to nie ma co hakować.

Wybieramy sobie zakładkę Bazy danych na samej górze. W nowym okienku podajemy nazwę bazy danych, oraz metodę porównywania napisów, najlepiej UTF-8 General.

Nowa baza danych
Nowa baza danych

Klikamy w przycisk Utwórz.

Teraz wybieramy naszą nową bazę danych z listy po lewej stronie. W nowym oknie będziemy tworzyć nową tabelę. Potrzebujemy podać jej nazwę i liczbę kolumn – możemy podać złą, bo da się to zmienić w trakcie, ale zaprojektujmy naszą tabelę poprawnie.

  • id – identyfikator dla rekordów musi być. Jest to liczba, która jednoznacznie identyfikuje dany rekord w danej tablicy. Praktycznie każda tabela musi to mieć. My teoretycznie moglibyśmy pominąć ustalając jako jednoznaczy email czy login, ale zachowajmy konwencję,
  • login – jakiś musi być,
  • pass – hasło też się przyda,
  • email – do kontaktu z graczem,
  • add_date – data rejestracji,
  • last_login – ostatnie logowanie,
  • is_baned – czy gracz jest zbanownay, prosta flaga: 0 – niezbanowany, 1 – zbanowany.

Na początek starczy. Ważna sprawa. W tabelach nie upychamy wszystkiego jak leci. Przykładowo. Jeśli chcielibyśmy dodać opcję dodawania graczy do przyjaciół, nie dodamy do tej tabeli pola “przyjaciele” i nie będziemy wypisywać ich id po przecinku – szczególnie, że bycie przyjaciółmi jest dwustronne, więc musimy zmodyfikować aż dwa rekordy. Zamiast tego stworzylibyśmy nową tabelę friends o budowie:

  • id – bo musi być
  • first_friend_id – czyli id pierwszego gracza z tabeli graczy
  • second_friend_id  – czyli id drugiego gracza z tabeli graczy

Teraz mamy informację o obu, nie duplikujemy jej, do tego łatwiej to przeszukiwać.

Wróćmy do naszej nowej tabeli. Potrzebujemy 6 pól, a nazwiemy ją “players”.

Tworzymy tablicę
Tworzymy tablicę

O co tutaj chodzi?

  • id, mamy wartość liczbową, do tego ma indeks primary – co znaczy, że jest kluczem głównym. Czyli, dana wartość może się w tej kolumnie pojawić tylko raz. A_I, czyli omawiana wcześniej auto inkrementacja.
  • login, pass, emial – zwykłe ciągi tekstowe. Na hasło dlatego tak mało znaków, bo będziemy hashować tekst, więc nie przekroczy on nigdy tej długości – o hashowaniu później.
  • add_date i last_login, są typu daty i czasu. Ustawiamy domyślną wartość dla daty dodania.
  • is_baned – tinyint żeby zaoszczędzić miejsce. Domyślnie ustawiony na wartość 0.

Klikamy Zapisz. Mamy naszą tablicę. Czas się zająć kodem API. Ważna uwaga: Nie zamykaj okienka z phpMyAdmin, przyda się jeszcze.

Przygotowujemy API

Pierwszy krok do stworzenia kodu PHP, to przygotowanie pliku PHP. Najprościej zrobić go odpalając notatnik i zapisując plik jako: index.php. Nazwa może być inna, ale na serwerze pierwszy uruchamiany będzie zawsze plik index. Przykład:

Założmy, że mamy stronę www.example.com. Jeśli w folderze głównym serwera zrobimy folder test i dodamy do niego plik pliczek.php to wchodząc na stronę: www.example.com/test, dostaniemy błąd 404, czyli brak takiego adresu. Jednak podając: www.example.com/test/pliczek.php, uruchomimy kod. Jednak jeśli do folderu test, dodamy plik index.php, to żeby dostać się do niego, nie potrzebujemy wklepywać: www.example.com/test/index.php, bo serwer sam poszuka pliku index.php i wystarczy wprowadzić: www.example.com/test.

Teraz trzeba wrzucić ten plik na serwer. Najprościej wykorzystać do tego protokół FTP. Nadadzą się do tego programy takie jak FileZilla czy TotalCommander, oraz zapisany wcześniej adres do serwera FTP, login i hasło.

Po zalogowaniu znajdźcie folder public_html i albo wrzućcie sobie tam index.php, albo stwórzcie jakiś folder i plik unieście w folderze. Rekomenduję drugie rozwiązanie.

Plik zostanie na lokalnym komputerze, bo wysyłana jest jego kopia. Sam pusty plik jeszcze nic nie robi, więc nie ma na razie co testować. Jednak omawiam ten punkt, żeby później każdy był w stanie samodzielnie plik wrzucić.

Przeglądarkowy klient API

Czas przygotować nasz kod. Jako IDE do pisania w PHP nada się… wszystko. Można to zrobić w notatniku, w NetBeansie, Eclipse i w sumie we wszystkich. Z lekkich fajnych edytorów polecam Notepad++, jak notatnik, tylko koloruje składnie.

Zacznijmy od bardzo podstawowego kodu:

<?php
	echo "Hello World";
?>

Ten kod nie robi nic innego jak wypisanie standardowego tekstu.

Co jest tutaj ważne? Plik PHP zaczynamy od <?php, a kończymy na ?>. Średnik obowiązuje. Ogólnie kod bardzo przypomina C# czy C++ – bo na tym języku bazuje. Więc jak ktoś zna jeden język, nie powinien mieć problemów.

OK. Tak przygotowany plik index.php przesyłamy na serwer i wchodzimy na naszą stronę, budując adres tak jak podawałem wcześniej: www.adresStrony.prv.pl/folder/ Jeśli wszystko jest OK, to powinno wyświetlić się takie coś:

Hello World w PHP
Hello World w PHP

Zasadniczo potrzebujemy dwóch funkcji: Rejestrująca – wprowadza nowego użytkownika, oraz autoryzująca – sprawdza czy podany login i hasło są poprawne.

Problem jest jeden. W komunikacji internetowej mamy dwa sposoby przesyłania danych. Jawny: GET i mniej jawny: POST. GET pewnie nie raz widzieliście. Kiedy mamy adres internetowy: www.example.com/test/?zmienna=5&akcja=dodaj, to znak zapytania informuje, że dalsza część adresu to zmienne przesyłane za pomocą GET, znak & oddziela kolejne zmienne, a po obu stronach znaku równości mamy nazwę zmiennej i wartość. Oczywiste jest, że taka metoda przesyłu danych nie jest zbyt bezpieczna i wykorzystuje się ją przy przesyłaniu zmiennych, którymi użytkownik nie może zrobić krzywdy stronie – np. przy paginacji podajemy tak numer strony, którą chce przeglądać. W kluczowych momentach wykorzystuje się metodę POST, z nią jest taki problem, że nie da się z “palca” wysłać zmiennych w ten sposób, co utrudnia testowanie, bo trzeba sobie przygotować formularz testowy, który zasadniczo sprowadza się do bycia klientem www dla naszego API, ale zmusza nas do liźnięcia HTMLa.

Kod całego naszego pliku teraz wygląda tak:

<?php

?>

<form method="POST" action="">
	<input type="hidden" name="form_type" value="register" />
	<input type="text" name="user_login" value="" placeholder="login..." /> <br/>
	<input type="password" name="user_pass_01" value="" placeholder="haslo..." /> <br/>
	<input type="password" name="user_pass_02" value="" placeholder="powtorz haslo..." /> <br/>
	<input type="text" name="user_email" value="" placeholder="e-mail..." /> <br/>
	<input type="submit" value="Rejstruj" />
</form>

Kod PHP dopiszemy później. Skupmy się na HTMLu. Operujemy tu znacznikami. Mamy znaczniki 2 elementowe, gdzie mamy tag otwierający i zamykający (form), oraz takie jednoelementowe, gdzie tag jest pojedynczy.

Znacznik form, tworzy nam formularz, który da się wysłać. Parametr method, to omawiana wcześniej forma przesyłania danych. Akcja wskazuje jaki adres powinien być wykonany, gdy zostawimy puste, wykona się strona na której jesteśmy, co nam wystarcza.

Znacznik input tworzy element formularza. Type wskazuje na jego typ: hidden – ukryte, text – tekstowy, password – hasłowy, czyli tekst jest wygwiazdkowany, submit – przycisk do wysyłania formularza. Name to nazwa pola, co jest kluczowe przy odbiorze danych. Value to aktualna wartość. Placeholder to tekst który się pojawi, gdy w polu nie ma wartości.

Znacznik <br/> to przejście do kolejnej linii. Taki kod, daje taki efekt:

Pierwszy formularz
Pierwszy formularz

Tylko, że w tej chwili jesteśmy w stanie wyświetlić tylko kod rejestracyjny. A chcemy mieć też dostęp do kodu logowania. Można to zrobić dwojako. Przygotować dodatkowy plik, albo wykorzystać zmienne typu GET. My wykorzystamy zmienne GET. Dlatego modyfikujemy kod do takiej postaci:

<?php
	$page = $_GET['action']; 
	if(is_null($page)) {
		$page = $_POST['action'];
	}
	
	if($page == "login") {
		
	} 
	
	if($page == "register") {
		
	}
?>

<?php if($page == "login"): ?>
<form method="POST" action="">
	<input type="hidden" name="action" value="login" />
	<input type="text" name="user_login" value="" placeholder="login..." /> <br/>
	<input type="password" name="user_pass" value="" placeholder="haslo..." /> <br/>
	<input type="submit" value="Loguj" />
</form>
<?php elseif($page == "register"): ?>
<form method="POST" action="">
	<input type="hidden" name="action" value="register" />
	<input type="text" name="user_login" value="" placeholder="login..." /> <br/>
	<input type="password" name="user_pass_01" value="" placeholder="haslo..." /> <br/>
	<input type="password" name="user_pass_02" value="" placeholder="powtorz haslo..." /> <br/>
	<input type="text" name="user_email" value="" placeholder="e-mail..." /> <br/>
	<input type="submit" value="Rejstruj" />
</form>
<?php endif; ?>

Na początku w oczy rzuca się to, że znacznikami <?php i ?> sobie wręcz rzucam po kodzie. Można tak, ważne, żeby kod PHP znajdował się między nimi. Dzięki takiemu zapisowi, kod HTMLa można podać wprost. W przeciwnym wypadku, musielibyśmy pisać coś takiego:

echo '<form method="POST" action="">';

I tak dla każdej linijki. Mało wygodne i przejrzyste.

Druga charakterystyczna rzecz, to fakt że raz używam ” “, a raz ‘ ‘.  Nie ma to znaczenia. Zasadniczo można używać jednego bądź drugiego. Różnice są, ale niezauważalne na tym poziomie.

Mamy też dwa zapisy ifa, ten z dwukropkiem jest przeznaczony właśnie do takiego mieszanego zapisu z HTMLem. Drugi jest znany. If wygląda jak w C# więc nie omawiam.

Ciekawostką mogą być za to zmienne: $_POST i $_GET. Są to tablice globalne w PHP, które są zawsze – takich tablic jest więcej i mają różne przeznaczenie. Te dwie służą do przetrzymywania zmiennych przesłanych metodą odpowiednio: POST i GET.

Co robi ten fragment:

$page = $_GET['action']; 
if(is_null($page)) {
	$page = $_POST['action'];
}

Do zmiennej $page pakujemy wartość z tablicy GET dla klucza action. Jeśli zmienna dalej jest nullem, to pobieramy wartość z tablicy POST, bo wartości przesyłamy sobie formularzem.

Tutaj uwaga: zmienne w PHP zaczynają się od znaku dolara. Nie musimy ich deklarować, mają dowolny typ i mogą go dynamicznie zmieniać w trakcie działania skryptu – tak w PHP piszemy skrypty, język jest interpretowany, nie kompilowany. Czyli interpreter wykonuje jego kod linijka po linijce, nie musi “rozkminić” całego i skompliować go do programu wykonywalnego.

Teraz na koniec pliku dodajmy jeszcze takie coś:

<br/>
<a href="?action=register">Register</a> | 
<a href="?action=login">Login</a>

Znacznik a, tworzy nam link. W parametrze href podajemy adres, a pomiędzy tagami otwierającym i zamykającym treść linku. Przykładowo w href można podać: http://google.com i taki link przekieruje do Googli. To co ja zapisałem, przeniesie nas do strony pod jaką się znajdujemy, ale podmieni parametry GET na to co ja podałem. Teraz możemy się łatwo przemieszczać między formularzami.

Kodujemy API

Czas teraz napisać samo API. Zaczniemy od rejestracji:

<?php
	$servername = 'localhost';
	$username = 'TwojLogin';
	$password = 'TwojeHaslo';
	$dbname = 'unity_test'; 

	$page = $_GET['action']; 
	if(is_null($page)) {
		$page = $_POST['action'];
	}
	
	if($page == "login") {
		
	} 
	
	if($page == "register") {
		if ($_SERVER['REQUEST_METHOD'] === 'POST') {	
			
			$login = trim(strip_tags($_POST['user_login']));
			$password1 = trim(strip_tags($_POST['user_pass_01']));
			$password2 = trim(strip_tags($_POST['user_pass_02']));
			$email = trim(strip_tags($_POST['user_email']));
			
			if($password1 != $password2) {
				die("Passwords are different");
			}
			
			$conn = new mysqli($servername, $username, $password, $dbname);
			// Check connection
			if ($conn->connect_error) {
				die("Connection failed: " . $conn->connect_error);
			} 
			
			$sql = "INSERT INTO players (login, pass, email) VALUES ('".$login."', '".md5($password1)."', '".$email."')";

			if ($conn->query($sql) === TRUE) {
				$result = array('status' => 1, 'msg' => "Success");
			} else {
				$result = array('status' => 0, 'msg' => $conn->error);
				
			}
			
			echo json_encode($result);
			$conn->close();
			die;
		}
	}
?>

// Tam dalej HTML bez zmian

Tak wygląda całość, ale skupmy się na zmodyfikowanych fragmentach. Pierwsze 4 linie to zmienne potrzebne do połączenia.

  • $servername – zostanie. Wcześniej mówiłem, że localhost to lokalny serwer. Względem pliku serwer na którym się znajduje, będzie dla niego lokalnym.
  • $username, $password – login i hasło do bazy danych – to samo co do phpMyAdmin
  • $dbname – nazwa bazy danych. W przykładzie stworzyliśmy bazę danych unity_test i z tą nazwą powinno się to pokrywać. Jeśli Twoja baza nazywa się inaczej, tutaj musisz to uwzględnić.

Teraz będę kod omawiał krótkimi fragmentami:

if ($_SERVER['REQUEST_METHOD'] === 'POST')

Ten if sprawdza, czy pojawił się request typu POST. Czyli, czy formularz został wysłany.

$login = trim(strip_tags($_POST['user_login']));

Tutaj ważne są funkcję trim – usuwa białe znaki z początku i końca ciągu tekstowego, oraz strip_tags – które usuwa tagi HTML i PHP, takie zabezpieczenie przed SQL Injection.

Kolejny if to sprawdzenie czy hasła są identyczne. Funkcja die, zatrzymuje interpretację kodu i wyświetla komunikat podany jako parametr.

$conn = new mysqli($servername, $username, $password, $dbname);
			
if ($conn->connect_error) {
	die("Connection failed: " . $conn->connect_error);
}

Tutaj mamy samo połączenie z bazą danych. Jeśli są błędy to je wyświetlamy.

$sql = "INSERT INTO players (login, pass, email) VALUES ('".$login."', '".md5($password1)."', '".$email."')";

Czas na składnie języka SQL. Ogólnie w SQL mamy 4 typy zapytań: Select – pobranie danych, Delete – usunięcie danych, Insert i Put – umieszczenie danych. Składnia insert jest prosta, mamy słowo kluczowe: INSERT, następnie INTO po którym następuje nazwa tabeli do której chcemy wstawiać. W nawiasie podajemy kolumny. Później słowo kluczowe VALUES i w nawiasie wartości dla poszczególnych kolumn. Jeśli w nazwach kolumn login był pierwszy, to tutaj musimy podać wartość dla tej kolumny jako pierwszą.

Funkcja md5 to hashowanie, albo inaczej funkcja skrótu. To co robi, to sprowadzenie każdego ciągu znaków, do 128 bitowego hasha. Co nam to daje? Przykładowo takie coś: MD5(“Ala ma kota”) da nam: 91162629d258a876ee994e9233b2ad87. Efekt? Funkcja skrótu jest jednokierunkowa. Czyli, gdy ktoś nawet przechwyci tak zapisane hasło, nie jest w stanie go odkodować – da się to zrobić, generując funkcję skrótu dla kolejnych słów i porównywać je z przechwyconym. Jeśli hasło nie będzie oczywiste, typu: “admin”, “haslo” etc. to złamanie hasa w ten sposób może trwać nawet lata.

Sama kropka w stringu, to metoda łączenia stringów, tak jak w C# odpowiada za to +.

if ($conn->query($sql) === TRUE) {
	$result = array('status' => 1, 'msg' => "Success");
} else {
	$result = array('status' => 0, 'msg' => $conn->error);				
}
			
echo json_encode($result);
$conn->close();
die;

Ostatni fragment kodu to wywołanie przygotowanego kodu SQL i przygotowanie tablicy z odpowiedzią. Status odpowiedzi: 1 – sukces, 0 – błąd. Oraz komunikatu. Umieszczamy obie zmienne w tablicy. Następnie wypisujemy je, sprowadzając obie do formatu JSON, korzystając z funkcji json_encode. Inaczej przesłanie tablicy zakończyłoby się porażką, albo błędem – po prostu goła tablica nie nadaje się do przesyłania w internecie.
[stextbox id=”info” defcaption=”true”]JSON – Fomat zapisu danych w formie ciągu tekstowego, obsługiwany przez niemal wszystkie języki.[/stextbox]
Na koniec zamykamy połączenie i kończymy operację. Dzięki temu po wykonaniu operacji wypiszemy tylko wynik w formie stringa. Dokładnie to odbierze później klient, dlatego dodajemy die, aby nie pobierał też formularza.

Wgrywamy plik na serwer, wypełniamy formularz i wysyłamy go. Jeśli wszystko poszło dobrze, w naszej bazie danych zobaczymy coś takiego:

Efekt po wykonaniu zapytania z formularza rejstracji
Efekt po wykonaniu zapytania z formularza rejstracji

Ponieważ kolumnie add_date is is_baned daliśmy domyślne wartości to automatycznie się ustawiły. Id jako klucz podstawowy z automatycznym wzrostem wartości również sam sobie ustawił wartość. Last_login został ustawiony na wartość pustą.

No to dopiszmy logowanie. Kod ląduje w drugim ifie:

if ($_SERVER['REQUEST_METHOD'] === 'POST') {	
	
	$login = trim(strip_tags($_POST['user_login']));
	$passwd = trim(strip_tags($_POST['user_pass']));
	
	$conn = new mysqli($servername, $username, $password, $dbname);
	
	if ($conn->connect_error) {
		die("Connection failed: " . $conn->connect_error);
	} 
	
	$sql = "SELECT * FROM players WHERE login LIKE '" . $login . "'";
	$result = $conn->query($sql);
	
	if ($result->num_rows > 0) {
		$user = $result->fetch_assoc();
		
		if(md5($passwd) != $user['pass']) {
			$result = array('status' => 0, 'msg' => "Wrong Password");
		} else {
			$result = array('status' => 1, 'msg' => "Success!");
		}			
	} else {
		$result = array('status' => 0, 'msg' => "There is no such user");
	}
	
	echo json_encode($result);
	$conn->close();
	die;
}

Składnia SELECT jest chyba dość prosta: słowo kluczowe SELECT, po czym podajemy kolumny które chcemy pobrać – gwiazdka oznacza wszystkie. Następnie mamy słowo kluczowe FROM, a po nim nazwę tabeli, z której chcemy wydobyć dane. Potem mogą pojawić się opcjonalne parametry. My skorzystaliśmy z WHERE, czyli warunku. Szukamy rekordów, dla których login jest identyczny z podanym przez użytkownika.

Jeśli mamy więcej niż jeden rekord to przechodzimy dalej w przeciwnym wypadku zwracamy błąd.

$user = $result->fetch_assoc();

Ten kod do zmiennej $user wprowadza pierwszy rekord jako tablicę asocjacyjną, gdzie nazwy kolumn są kluczami w tablicy. W przypadku, gdybyśmy chcieli wypisać wszystkich użytkowników, zrobilibyśmy coś takiego:

while($row = $result->fetch_assoc()) {
    echo "id: " . $row["id"]. " - Login: " . $row["login"]. "<br>";
}

Drugi wewnętrzny if to sprawdzenie czy hash podanego hasła pokrywa się z zapisanym w bazie dla danego użytkownika. Jeśli wszystko się zgadza zwracamy sukces.

Można testować.

Podsumowanie

Skończone. Przygotowaliśmy sobie bazę danych oraz API. Dodatkowo stworzyliśmy prostego klienta www do korzystania z API. W kolejnej części zajmiemy się klientem w edytorze Unity.

Jak wspomniałem, nie ma tutaj zabezpieczania przesyłanych danych. Zrobimy to na końcu. Całość tutaj też nie jest w pełni profesjonalna, bo zajęłoby to znacznie więcej miejsca i czasu, a nie to jest tutaj najważniejsze. Przykładowo nie dbamy o to, żeby loginy i emaile się nie powtarzały. Całość można by było robić, żeby PHP i HTML znajdowały się w oddzielnych plikach, logowanie było na oddzielnej stronie względem rejestracji etc. Jednak nie PHP i HTML jest przedmiotem dyskusji, więc nie omawiałem więcej niż potrzeba.

Jeśli coś jest nie jasne, to komentarze są do dyspozycji.