Meteor – autopublish oraz insecure

 In Technicznie

Czym jest Meteor?

Tematem dzisiejszego wpisu będzie platforma programistyczna Meteor – framework oparty o język JavaScript przeznaczony do tworzenia reaktywnych aplikacji www oraz mobilnych. Aplikacje takie nie wymagają odświeżania by modyfikować wyświetlaną treść, w działaniu przypominają więc aplikacje desktopowe. Platforma jest dostępna na systemy Linux, Windows oraz OS X.

Meteor zmienia klasyczne podejście do programowania aplikacji www poprzez ujednolicenie kodu klienta i serwera – zarówno do frontendu jak i backendu wykorzystujemy język JavaScript. Meteor domyślnie wykorzystuje obiektową bazę danych MongoDB. Dostęp do niej danych realizowany jest nie na zasadzie zapytań, a mechanizmu publikacji oraz subskrypcji pozwalającego na błyskawiczne przedstawienie zmian w bazie użytkownikowi końcowemu. Mechanizm ten znacząco ułatwia dostęp do bazy danych (pojedynczą publikację możemy wykorzystać wielokrotnie w różnych miejscach aplikacji), posiada jednak kilka specyficznych zachowań o których należy pamiętać, a które postaram się wyjaśnić w dzisiejszym wpisie.

Przykładowa aplikacja

Zacznijmy od pobrania i uruchomienia przykładowej aplikacji przygotowanej przez twórców frameworka. W tym celu musimy zainstalować pakiet Meteor – aktualne informacje jak to zrobić na poszczególnych systemach operacyjnych znajdziemy na stronie Meteor.com, ja korzystam z systemu Ubuntu więc instaluję pakiet przez polecenie w terminalu:

Następnie wykorzystamy przykładową aplikację przygotowaną przez twórców Meteora. W konsoli systemu przechodzimy do folderu w którym ma się ona znajdować i wykonujemy polecenie:

które utworzy folder “todos” i pobierze do niego aplikację. Aby ją uruchomić przechodzimy do nowo utworzonego folderu i i uruchamiamy serwer meteora:

po otworzeniu przeglądarki powinniśmy zobaczyć prostą listę rzeczy do zrobienia.

Aplikacja Todos

Autopublish i insecure

Te dwa pakiety, zainstalowane automatycznie w każdym nowym projekcie (za wyjątkiem przykładowych), pozwalają nam na bardzo szybkie prototypowanie naszej aplikacji. Paczka insecure pozwala na dowolne zmiany w bazie ze strony klienta, a autopublish zapewnia dostępność wszystkich danych z dowolnego miejsca aplikacji.

Autopublish

W omawianej aplikacji “todos” autopublish jest już wyłączony, a dane są udostępniane na zasadzie publikacji i subskrypcji dla poszczególnych list. Kod publikacji możemy znaleźć w pliku server/publish.js:

Przykładowa publikacja powyżej odpowiada za pokazywanie list prywatnych tylko użytkownikowi, który jest ich właścicielem. Natomiast subskrypcję korzystającą z tej publikacji znajdziemy w pliku lib/router.js:

Powyższe subskrypcje pozwalają na pobranie odpowiednio list publicznych, widocznych dla wszystkich użytkowników, oraz prywatnych tylko dla ich twórcy. Ich działanie można zaobserwować tworząc nową listę prywatną i próbując podejrzeć ją bez logowania:

Autopublish off - zalogowany

Widok dla niezalogowanego użytkownika:

Autopublish off - niezalogowany

Co by się stało gdybyśmy jednak pozostawili pakiet autopublish w naszej aplikacji? Sytuację taką możemy zasymulować zatrzymując serwer, dodając pakiet autopublish i uruchamiając go na nowo:

W konsoli pojawi się ostrzeżenie przypominające o aktywnym autopublishu:

Teraz widok list dla niezalogowanego użytkownika wygląda tak:

Autopublish on - niezalogowanyJak widzimy warto więc na pewnym etapie rozwoju aplikacji rozpisać publikacje i subskrypcje, a pakiet autopublish usunąć.

Insecure

W aplikacji “todos” pakiet insecure nadal jest zainstalowany. Oznacza to iż użytkownik jest w stanie zmieniać dowolne dane w bazie (nie tylko te dotyczące jego):

Insecure - update bazy

Ze względów bezpieczeństwa wolelibyśmy by wszystkie zapisy do bazy były wcześniej weryfikowane za pomocą metod serwerowych, a dopiero potem zapisywane. Zatem tak samo jak w przypadku pakietu autopublish, insecure również powinien być usunięty po utworzeniu metod zarządzających bazą danych. Od momentu jego usunięcia, aby zezwolić klientowi na modyfikację bazy należy napisać specjalną regułę która to umożliwia – bez niej nie uda się nam dodać nowych elementów do listy:

Jak widać pozwalamy w niej na dodawanie nowych elementów gdy lista jest publiczna (nie ma właściciela) lub właścicielem jest obecnie zalogowany użytkownik. Podobnie należałoby utworzyć reguły dla akcji ‘update’ oraz ‘delete’, ale nie to jest istotą tego wpisu.

Mogłoby się wydawać iż odinstalowując pakiet insecure oraz tworząc poszczególne reguły zabezpieczające nasza aplikacja będzie dobrze zabezpieczona przed nieuprawnionym dostępem ze strony użytkownika. Jest jednak jeden problem – użytkownik może w dowolnej chwili aktualizować w bazie swoje konto, nawet gdy nie istnieje reguła która na to zezwala. Możemy to zilustrować prostym przykładem:

w pliku app-body.html po sekcji {{emailLocalPart}} dodajemy nowy helper (jest to miejsce które Meteor wypełni danymi pobranymi z funkcji o tej samej nazwie):

a następnie w pliku app-body.js w sekcji Template.appBody.helpers definiujemy jego działanie:

co w efekcie da nam prosty wskaźnik stanu konta:

Insecure - stan konta

Jednak wspomniana wcześniej możliwość edycji konta użytkownika pozwala na wykonanie takiej operacji:

Insecure - edycja konta

Pomijam tu oczywiście sensowność zapisu tak wrażliwych danych w profilu użytkownika, ale dobrze ilustruje to problem. Aby zapobiec takiej sytuacji możemy napisać regułę która jawnie zabroni jakichkolwiek aktualizacji profilu użytkownika. Możemy ją umieścić np. w pliku collections.js:

Po jej dodaniu modyfikacja profilu użytkownika przestanie być możliwa.

Insecure - edycja konta zablokowana

Recent Posts