Posts tagged Router

3 część kursu Router

Zapraszam na trzecią część kursu o wzorcu Router. W tej części pokazałem jak zrobić algorytm odnajdywania właściwego kontrolera oraz jak zapisać nazwę kontrolera, metody i argumentów. Zapraszam serdecznie do lektury:

Router – część 3

Uwagi i komentarze mile widziane 🙂

Wzorce projektowe: Router – cz. 2

Informacje wstępne

W tej części chciałbym skupić się na prostej metodzie filtrowania niebezpiecznych znaków na wejściu.

Implementacja

Ostatni raz klasa miała następującą postać

class Router {

    public static $current_uri  = '';

    public static function get_uri()
    {
        if (!empty($_SERVER['PATH_INFO']))
        {
            self::$current_uri = $_SERVER['PATH_INFO'];
        }
    }
}

Dodajmy więc następne elementy. Zaznaczone na zielono.

class Router {

    public static $current_uri  = '';

    public static function get_uri()
    {
        if (!empty($_SERVER['PATH_INFO']))
        {
            self::$current_uri = $_SERVER['PATH_INFO'];
        }

        self::$current_uri = trim(self::$current_uri, '/ ');

        if (self::$current_uri !== '')
        {
            self::$current_uri = preg_replace('#//+#', '/', self::$current_uri);

            self::$current_uri = str_replace(' ', '_', self::$current_uri);

            self::$current_uri = preg_replace("/[^a-z0-9\\-\\_\\/\\,]/i", '', self::$current_uri);
        }
    }
}
  1. W linii 12 dodaliśmy funkcję “trim”, która obcina po lewej i po prawej stronie tekstu znaki, które podamy w parametrze. Domyślnie usuwa białe znaki (spacja, enter, tabulator). My chcemy pozbyć się niepotrzebnych slashy i białych znaków.
  2. Następnie sprawdzamy czy cokolwiek po tej operacji zostało w zmiennej $current_uri (linia 14). Jeśli jest różne od pustego ciągu do wykonujemy dodatkowe zabezpieczenie
  3. W linii 14 wyrażenie regularne usuwa wielokrotne slashe, np: jeśli na wejściu będzie “konto///klient//zobacz” to zamieni to na “konto/klient/zobacz”
  4. W linii 18 spacje zamieniane są na podkreślniki. To jeden z najprostszych sposobów oddzielania wyrazów w adresach stron. Ewentualnie można jeszcze zastosować myślnik
  5. Wreszcie w linii 20 wyrażenie regularne usuwa z wejścia wszystko co nie jest znakiem dopuszczanym (nie znajduje się na liście). W tym przypadku wyrażenie regularne pozostawi tylko znaki alfanumeryczne, przecinek i slash. W zależności od potrzeb można ta listę wydłużyć/zmienić

Ostateczna postać klasy:

class Router {

    public static $current_uri  = '';

    public static function get_uri()
    {
        if (!empty($_SERVER['PATH_INFO']))
        {
            self::$current_uri = $_SERVER['PATH_INFO'];
        }

        self::$current_uri = trim(self::$current_uri, '/ ');

        if (self::$current_uri !== '')
        {
            self::$current_uri = preg_replace('#//+#', '/', self::$current_uri);

            self::$current_uri = str_replace(' ', '_', self::$current_uri);

            self::$current_uri = preg_replace("/[^a-z0-9\\-\\_\\/\\,]/i", '', self::$current_uri);
        }
    }
}

Przykładowe wywołanie kodu:

Router::get_uri();
echo Router::$current_uri;

Kod wywołania nie zmienił się. Spróbuję jednak podać przykład “brzydkiego” wejścia.

http://moja.strona/stroąna[45],param1/zob&*acz

Efekt powinien być taki:

strona45,param1/zobacz

Jak widać wejście dobrze zabezpieczone – zezwala tylko na takie znaki jakie ma zdefiniowane

Podsumowanie

Starałem się krótko przedstawić proste zasady uniknięcia problemów i nieprzyjemności z dalszymi operacjami na wejściu. Można oczywiście mnożyć ilość przypadków, znaków i sytuacji które należy obsłużyć ale podane reguły sa na obecną chwilę całkowicie wystarczające.

Przedstawione zabezpieczenia nie mają na celu doprowadzić adresu z wejścia do czegoś konkretnego. Np jeśli nasza aplikacja posiada akcję “/klient/logowanie” a ktoś zamiast tego wpisze (np haker) /klient/logowanie” albo sql injection w stylu “/klient/’ or 1=1 ‘” itd to system niebezpieczne ciągu znaków odrzuci i zostawi tylko to co się nadaje i jest bezpieczne. W związku z tym dalej możemy szukać czy mimo wszystko coś sensownego z tego da się wyciągnąć. Tworząc linki w naszej aplikacji wiemy jakie one są: np na stronie głównej zrobimy “/klient/logowanie” ale to nie znaczy, że ktoś ręcznie w przeglądarce wpisze sobie coś innego (czego nie jesteśmy w stanie przewidzieć). Dzięki tym zabezpieczeniom system najwyżej takiej osobie, która próbuje manipulować linkami powie, że taka strona nie istnieje i nie wpłynie to na bezpieczeństwo samej aplikacji. Ustalmy, że to Router ma dostarczyć dane w sposób bezpieczny tak, aby reszta aplikacji nie musiała się już tym martwić

W następnym artykule przedstawię sposób rozbicia wejścia na użyteczne informacje

Nowy kurs – Router

Przygotowałem dosyć krótki i prosty wstęp z przykładową implementacją wzorca projektowego Router. Krok po kroku będę prezentował kolejne etapy rozwoju i implementacji poszczególnych elementów tego obiektu.

Zapraszam serdecznie do zapoznania się z pierwszym artykułem na ten temat – Router
Zobacz także ogólnie – Wzorce projektowe

Wzorce projektowe

Wzorce Projektowe, które powstały po to aby w miarę spójnie rozwiązywać problemy przy projektowaniu systemów.

O wzorcach projektowych powstało na pewno wiele mądrych i obszernych książek więc nie ma sensu abym ja się tutaj rozpisywał.

Przygotowałem kursy i implementacje popularnych i często używanych w programowaniu wzorców projektowych.

Wzorce projektowe: Router – cz. 1

Informacje wstępne

Co to takiego ten Router i do czego on służy? Podobnie jak od strony technicznej jest to pewien “byt” zajmujący się odnajdywaniem/trasowaniem/przekazywaniem zadanych żądań.
W programowaniu Router to jeden z tzw Wzorców Projektowych, które powstały po to aby w miarę spójnie rozwiązywać problemy przy projektowaniu systemów.

O wzorcach projektowych powstało na pewno wiele mądrych i obszernych książek więc nie ma sensu abym ja się tutaj rozpisywał. Po co nam ten Router? Routerem nazwiemy obiekt, który będzie się zajmował pobieraniem adresu z przeglądarki i przetwarzaniem go na akcję zrozumiałą dla pozostałych elementów systemu. To on będzie decydował o tym, co ma się pojawić na wyjściu gdy pojawi się coś na wejściu.

Przykład:
Jeśli wpiszemy w przeglądarce:

http://moja.strona/witaj

Router odbierze na wejściu “witaj” i wg jemu znanego systemu przekaże dalej to żądanie – np “powie” systemowi, że należy wyświetlić stronę z powitaniem. Inny przykład:

http://moja.strona/

Router może mieć zaprogramowane domyślne akcje w przypadku braku konkretnych żądań. Przykładowo jeśli nie podano nic na wejściu to Router przekaże, że należy wyświetlić stronę główną.

Implementacji takiego systemu jest tak wiele jak i programistów jednakże pewne zasady ze względu na wzorce projektowe i wymagania techniczne są niezmienne i konieczne do poprawnego zrealizowania zadania.

Implementacja

W kolejnych krokach postaram się opracować prostą ale w pełni funkcjonalną implementację takiej klasy. Zacznijmy od opracowania podstawowych metod tej klasy

class Router {

    public static $current_uri  = '';

    public static function get_uri()
    {
        if (!empty($_SERVER['PATH_INFO']))
        {
            self::$current_uri = $_SERVER['PATH_INFO'];
        }
    }
}

Pole $current_uri będzie przechowywać pobrany adres na wejściu – zostanie on użyty później.
Metoda get_uri() powinna zostać uruchomiona na początku działania systemu. Jej zadaniem jest pobranie z pola tablicy superglobalnej $_SERVER wartości PATH_INFO. Pod tym polem kryje się wszystko to co zostało zapisane za plikiem, który uruchama skrypt – np index.php. Zatem jeśli w przeglądarce wpiszemy:

http://moja.strona/index.php/konto/rejestracja

To PATH_INFO będzie zawierało wartość

/konto/rejestracja

Zmienna $current_uri została domyślnie zainicjowana na wartość pustą. Jeśli jednak PATH_INFO było niepuste to przypiszmy tą wartość do $current_uri.

Przykładowe wywołanie kodu:

Router::get_uri();
echo Router::$current_uri;

Tyle ma do roboty Router jeśli chodzi o odbieranie danych.

Podsumowanie

To jest oczywiscie bardzo prosta implementacja jednakże w pełni skuteczna i wystarczająca do dalszej “obróbki”. W kolejnej części postaram się pokazać podstawowe sposoby zabezpieczenia wejścia i rozbijanie wejścia na konkretne akcje.

Następna część: Router cz. 2

Go to Top