Możliwa duplikat:
pisanie internetowych aplikacji „bez serwera”
Powiedzmy, że zbuduję klon Stack Exchange i zdecyduję się użyć czegoś takiego jak CouchDB jako mojego sklepu z zapleczem. Jeśli korzystam z wbudowanego uwierzytelniania i autoryzacji na poziomie bazy danych, to czy jest jakiś powód, aby nie pozwalać skryptowi JavaScript po stronie klienta pisać bezpośrednio na publicznie dostępnym serwerze CouchDB? Ponieważ jest to w zasadzie aplikacja CRUD, a logika biznesowa polega na tym, że „tylko autor może edytować swój post”, nie widzę potrzeby posiadania warstwy między elementami po stronie klienta a bazą danych. Po prostu użyłbym sprawdzania poprawności po stronie CouchDB, aby upewnić się, że ktoś nie wprowadza śmieciowych danych i upewnić się, że uprawnienia są ustawione poprawnie, aby użytkownicy mogli czytać tylko własne dane użytkownika. Renderowanie byłoby wykonywane po stronie klienta przez coś takiego jak AngularJS. W gruncie rzeczy możesz mieć serwer CouchDB i kilka „statycznych” stron i możesz zacząć. Nie potrzebujesz żadnego przetwarzania po stronie serwera, tylko coś, co mogłoby obsłużyć strony HTML.
Otwarcie mojej bazy danych na świat wydaje się niewłaściwe, ale w tym scenariuszu nie mogę wymyślić, dlaczego, dopóki uprawnienia są ustawione poprawnie. Jest to sprzeczne z moim instynktem jako programisty stron internetowych, ale nie mam dobrego powodu. Dlaczego to zły pomysł?
EDYCJA: Wygląda na to, że jest tutaj podobna dyskusja: Pisanie aplikacji internetowych „bez serwera”
EDYCJA: Jak dotąd niesamowita dyskusja i doceniam opinie wszystkich! Wydaje mi się, że powinienem dodać kilka ogólnych założeń zamiast wzywać CouchDB i AngularJS. Załóżmy więc, że:
- Baza danych może uwierzytelniać użytkowników bezpośrednio z ukrytego sklepu
- Cała komunikacja z bazą danych odbywa się za pośrednictwem protokołu SSL
- Sprawdzanie poprawności danych może (ale może nie powinno?) Być obsługiwane przez bazę danych
- Jedyną autoryzacją, na której nam zależy, poza funkcjami administracyjnymi, jest możliwość edytowania własnego postu
- Nie ma problemu, że każdy może odczytać wszystkie dane (Z WYJĄTKIEM rekordów użytkowników, które mogą zawierać skróty haseł)
- Funkcje administracyjne byłyby ograniczone przez autoryzację bazy danych
- Nikt nie może dodać się do roli administratora
- Baza danych jest stosunkowo łatwa do skalowania
- Prawdziwa logika biznesowa jest niewielka lub żadna; jest to podstawowa aplikacja CRUD
źródło
DELETE FROM ImportantData;
Odpowiedzi:
Postępowanie zgodnie z sugestią tworzy ścisłe połączenie między językiem po stronie klienta a bazą danych.
To może być w porządku - jest mniej kodu do napisania i utrzymania, a teoretycznie debugowanie może / powinno pójść trochę szybciej.
Z drugiej strony utrudnia to inne aspekty. Jeśli / kiedy będziesz musiał zmienić którąś z tych technologii, będziesz miał trudniejszy czas z powodu ciasnego połączenia między nimi.
Zabezpieczenie się przed atakami będzie (dość) nieco trudniejsze. Zakładasz, że klient zawsze będzie prezentował ładnie sformatowane żądania w bazie danych. Zakłada się, że nikt nigdy nie zhakuje kodu po stronie klienta, aby wstawić złośliwe instrukcje. Innymi słowy, „pożyczą” one twoje mechanizmy uwierzytelnienia i zastąpią normalny kod klienta swoim.
Nie poleciłbym tego, a wielu stanowczo powiedziałoby ci, żebyś tego nie robił. Ale można to zrobić.
źródło
To chyba nie jest świetny pomysł. Pierwszym i najsilniejszym powodem, jaki mogę podać, jest to, że serwer bazy danych nie jest zaprojektowany jako publiczny serwer WWW. Przeciwnie, konwencjonalna mądrość mówi, że powinieneś ukryć swoją bazę danych za zaporą ogniową.
Jeśli potrzebujesz dowodów potwierdzających, istnieje wiele obaw - nie wszystkie nie do pokonania, ale wiele do przemyślenia. W żadnej konkretnej kolejności, oto kilka:
... I jestem pewien, że istnieją inne obawy. I jestem pewien, że istnieje rozwiązanie większości - jeśli nie wszystkich z tych obaw. Ale jest lista na początek!
źródło
Najlepszy pojedynczy powód, jaki mogę sobie wyobrazić, to: ponieważ ta metoda nie jest bezpośrednio obsługiwana ani zalecana przez żadną z zaangażowanych stron.
Dostawcy przeglądarek, standardy EcmaScript, programiści systemów baz danych, producenci sprzętu sieciowego, architekci hostingu / infrastruktury oraz specjaliści ds. Bezpieczeństwa nie obsługują (a nawet nie rozważają) proponowanego przypadku użycia. Jest to problem, ponieważ proponowana metoda wymaga, aby wszystkie te podmioty - i więcej - działały poprawnie dla Twojej aplikacji, nawet jeśli żaden z zaangażowanych systemów nie został zaprojektowany do obsługi tego.
Nie mówię, że to niemożliwe. Mówię tylko, że to mniej przypomina „ponowne wynalezienie koła”, a bardziej ponowne wynalezienie opartej na przeglądarce interakcji klient-serwer.
W najlepszym razie wykonasz mnóstwo pracy, aby nawet systemy działały na możliwie najbardziej podstawowym poziomie. Współczesne popularne bazy danych nie są RESTful'owe ani zbudowane do pracy przez HTTP, więc będziesz budował swoje własne (oparte na WebSocket) sterowniki klienta.
Nawet jeśli wszystko sprawdzi się technicznie, zrezygnujesz z wielu najpotężniejszych funkcji współczesnej architektury. Nie będziesz mieć dogłębnej obrony - każdy może łatwo połączyć się bezpośrednio z głównym celem większości prób włamań do witryny. Ale proponowany przez ciebie scenariusz jest znacznie gorszy.
Proponowany model nie tylko ujawnia serwer - ujawnia prawidłowe parametry połączenia. Atakujący nie mogą po prostu pingować serwera - mogą aktywnie się logować i podawać polecenia. Nawet jeśli możesz ograniczyć dostęp do danych, nie jestem świadomy wystarczającego oprzyrządowania w systemach DBMS do ochrony przed scenariuszami Denial of Service i ich podobnymi. Podczas pracy w ulepszonych wersjach SQL, takich jak TSQL, często niezwykle łatwo jest produkować bomby, które działają skutecznie nieskończenie długo (kilka nieograniczonych połączeń, aby stworzyć produkt kartezjański, a będziesz mieć WYBÓR, który będzie działał na zawsze, wykonując ciężką pracę) . Wyobrażam sobie, że musisz wyłączyć większość funkcji SQL, a nawet wyeliminować podstawowe zapytania SELECT za pomocą JOIN i być może zezwolić tylko na wywoływanie procedur przechowywanych? Nawet nie wiem, czy możesz to zrobić, nigdy nie zostałem poproszony o próbę. Nie robi
Skalowalność bazy danych jest również jednym z najtrudniejszych problemów w pracy na dużą skalę, podczas gdy skalowanie wielu serwerów HTTP - szczególnie ze stronami statycznymi lub buforowanymi - jest jedną z najłatwiejszych części. Twoja propozycja sprawia, że baza danych wykonuje więcej pracy, ponosząc odpowiedzialność w zasadzie za 100% aktywności po stronie serwera. To wada mordercza sama w sobie. Korzyści z przeniesienia pracy na klienta tracisz, przenosząc więcej pracy do bazy danych.
Na koniec chciałbym tylko podkreślić, że sedno tego, co proponujecie, nie jest nowe, ale faktycznie sięga dziesięcioleci. Model ten nazywany jest modelem „grubej bazy danych”, który zasadniczo przeniósł większość logiki po stronie serwera do bazy danych, tak jak proponujesz. Istnieje wiele powodów, dla których model ten przeszedł na masową skalę w Internecie, i prawdopodobnie warto byłoby przyjrzeć się bliżej tej historii. Zauważ też, że nawet wtedy niewiele było rozważań, aby całkowicie niezaufani użytkownicy mogli zalogować się do systemu i uruchamiać polecenia, ponieważ dostęp byłby nadal kontrolowany w celu wybrania wewnętrznych (znanych) użytkowników, którzy nie powinni stale atakować systemu.
Faktem jest, że nadal potrzebujesz serwera HTTP do obsługi plików, ponieważ systemy baz danych po prostu tego nie robią. Jednocześnie wszystko, co proponujesz, można uzyskać za pomocą cienkiego modelu serwera (takiego jak Nodejs) w celu udostępnienia interfejsu RESTful w bazie danych. Jest to popularne z jakiegoś powodu - działa, utrzymuje bazę danych w ukryciu za warstwami ochrony, jest niezwykle skalowalne, a jednak pozwala budować bazę danych tak grubą lub cienką, jak chcesz.
źródło
Cóż, przeniesienie autoryzacji (kwestie bezpieczeństwa) i walidacja logiki z dala od bazy danych zapewnia rozdzielenie problemów w systemie oprogramowania. W ten sposób można testować, konserwować, skalować i ponownie wykorzystywać logiczne bloki kodu przy mniejszym ryzyku hamowania funkcji w systemie.
Zapewnienie możliwości bezpośredniego wprowadzania danych przez klienta do bazy danych ma bardzo duży potencjał do zepsucia danych .
Oznacza to również, że unikanie / usuwanie ciasnego połączenia sprawia, że system oprogramowania jest łatwiejszy w utrzymaniu i SOLIDNY.
źródło
Umożliwienie użytkownikowi bezpośredniej interakcji z bazą danych wydaje mi się naprawdę niebezpieczne.
Czy mechanizm uwierzytelniania w CouchDB jest tak wyrafinowany, że można odizolować dostęp do odczytu i zapisu użytkownika tylko do danych, które ma on czytać i zapisywać (mówimy o dostępie do dokumentu, a może nawet do pola dokumentu) uprawnienia tutaj)? Co z danymi „wspólnymi”, które są udostępniane przez wielu użytkowników? Czy w ogóle nie ma tego w twoim projekcie aplikacji?
Czy naprawdę chcesz, aby użytkownik mógł W KAŻDY sposób zmieniać swoje dane? Co na przykład z zastrzykami XSS? Czy nie byłoby lepiej mieć warstwę serwera do filtrowania ich, zanim wejdą do bazy danych?
źródło
Masz wiele powodów, ale jest jeszcze jeden: zabezpieczenie na przyszłość. Wcześniej czy później, w miarę ewolucji aplikacji, pojawi się pewne wymaganie, którego nie można łatwo lub bezpiecznie osiągnąć w JS po stronie klienta lub jako procedurę przechowywaną w bazie danych.
Na przykład powiedziano ci, że wszystkie nowe rejestracje muszą mieć weryfikację CAPTCHA, aby były ważne. Byłoby to naprawdę łatwe z praktycznie każdym nowoczesnym środowiskiem aplikacji internetowych. Wystarczy uderzyć reCAPTCHA w formularzu rejestracyjnym, przekazać token odpowiedzi reCAPTCHA z powrotem do backendu i dodać kilka linii kodu do backendu, aby zweryfikować ważność tokena za pomocą API Google (lub jeszcze lepiej, użyj biblioteki, którą ktoś inny napisał, aby to zrobić dla Was).
Jeśli używasz systemu dwupoziomowego i polegasz na bazie danych dla całej logiki po stronie serwera, jak zamierzasz zweryfikować token? Tak, przypuszczam, że teoretycznie jest możliwe, w zależności od DBMS, napisanie procedury składowanej, która w jakiś sposób wywołuje powłokę i wywołuje curl z odpowiednimi argumentami. To prawie na pewno okropny pomysł: filtrowanie danych wejściowych i ochrona przed lukami w zabezpieczeniach byłyby straszne; miałbyś bałagan związany z obsługą błędów i przekroczeniami czasu; i musiałbyś sam przeanalizować odpowiedź. Nie wspominając już o tym, że DBMS nie jest przeznaczony do tego, więc nie ma powodu, aby sądzić, że wydajność, stabilność, bezpieczeństwo wątków itp. Nie będą problemami. Zobacz na przykład ten wątek , który omawia niektóre z tych problemów dotyczących Postgres.
I to tylko problemy związane z dodawaniem jednego prostego CAPTCHA do formularza. Co zamierzasz zrobić, jeśli chcesz dodać weryfikację SMS lub zadanie w tle, w którym nieaktywni użytkownicy wysyłają e-maile do nieaktywnych użytkowników, aby przypominać im o Twojej aplikacji, lub dodają funkcję przesyłania plików, aby ludzie mogli ustawić zdjęcie profilowe? Może zdecydujesz, że Twoja aplikacja będzie miała kiedyś zautomatyzowane testy? A może chcesz śledzić zmiany w procedurach w systemie kontroli wersji? Istnieje wiele bibliotek i narzędzi dla większości użytecznych języków do obsługi większości tych zadań, ale niewiele lub wcale nie będzie dostępnych dla Twojego DBMS, ponieważ nie jest to przeznaczone.
W końcu będziesz chciał zrobić coś, czego nie można racjonalnie zrobić bezpośrednio w DBMS, a następnie utkniesz. Ponieważ zbudujesz całą aplikację w DBMS, nie będziesz miał innego wyjścia, jak tylko zdobyć serwer WWW i rozpocząć odbudowę elementów w innym języku, aby dodać prostą funkcję.
To byłby prawdziwy wstyd, ponieważ mamy już nazwę miejsca, w którym umieszczasz logikę aplikacji, i to z jakiegoś powodu nazywa się to „kodem źródłowym aplikacji”, a nie „procedurami przechowywanymi w bazie danych”.
źródło
Jeśli kontrole bezpieczeństwa i logika biznesowa są zawarte w javascript po stronie klienta, mogą zostać zastąpione przez złośliwego użytkownika. Alternatywnie możesz wykorzystać technologię po stronie serwera opartą na JavaScript (np. Node.JS ) do obsługi sprawdzania poprawności, autoryzacji i tym podobnych.
źródło
Wszelkie ograniczenia biznesowe, które możesz chcieć zapewnić, powinny zostać zweryfikowane po stronie serwera. Nawet jeśli kontrolujesz dostęp użytkownika, ktoś może wysłać nieprawidłowe dane.
Zgodnie z przykładem klonowania przepływu stosu:
Każdy może manipulować kodem po stronie klienta i całkowicie naruszać integralność danych (nawet jeśli jest ograniczony do niektórych obiektów, takich jak ich własne posty).
źródło
Edytuj stronę w Firebug i w pewnym momencie wstaw linię podobną do tej:
ExecDbCommand("DROP TABLE Users")
Uruchom.
Edytować:
Pytanie było w rzeczywistości o CounchDB, więc nie ma tu sql do uruchomienia. Ale pomysł jest taki sam. Zakładam, że każda nietrywialna aplikacja zależy od danych w celu przestrzegania niektórych reguł spójności, które są sprawdzane / egzekwowane przez kod aplikacji. Złośliwy użytkownik może zmodyfikować kod klienta, aby zapisać dane w formie, która narusza reguły biznesowe i może spowodować spustoszenie w aplikacji.
Jeśli witryna uwzględnia wszystkie możliwe stany danych, które będą ważne z perspektywy biznesu następnie przez wszystkich środków pójść tą drogą, ale jeśli to nie jest przypadek (prawdopodobne), to chciałby mieć gwarancję, że wszelkie dane, które dostaje przechowywane są generowane przez TWOJEJ kod i zgodnie z twoimi zasadami .
źródło
Wiem, że to stare pytanie, ale chciałem się do niego odezwać, ponieważ moje doświadczenie różni się od innych odpowiedzi.
Spędziłem wiele lat pisząc aplikacje współpracujące w czasie rzeczywistym. Ogólnym podejściem do tych aplikacji jest lokalna replikacja danych i możliwie najszybsza synchronizacja zmian z urządzeniami równorzędnymi. Wszystkie operacje na danych są lokalne, więc przechowywanie danych, dostęp do danych, logika biznesowa i interfejs użytkownika są warstwami lokalnymi. Ruch „najpierw offline” ( http://offlinefirst.org/ ) przyjął to podejście do tworzenia aplikacji internetowych offline i może mieć pewne odpowiednie zasoby. Tego rodzaju przypadki użycia wymagają nie tylko otwarcia warstwy dostępu do danych dla klientów, ale także przechowywania danych! Wiem wiem. Wydaje się szalony, prawda?
Obawy dotyczące takich aplikacji offline są podobne do tych, o które prosiłeś, tylko jeden poziom został usunięty. Wydaje mi się to istotne. Biorąc pod uwagę, że otwierasz bezpośredni dostęp do danych dla klientów, pojawia się pytanie, w jaki sposób możesz ograniczyć skutki działania złośliwego użytkownika? Cóż, istnieje wiele strategii, ale nie są one oczywiste, jeśli pochodzisz z bardziej tradycyjnego środowiska programistycznego.
Pierwszym nieporozumieniem jest to, że ujawnienie bazy danych oznacza ujawnienie wszystkich danych. Weźmy na przykład CouchDB; bazy danych w CouchDB są lekkie, więc nie pomyślałbyś o stworzeniu setek tysięcy oddzielnych baz danych na serwerze. Użytkownicy mogą uzyskiwać dostęp tylko do baz danych, do których mają uprawnienia dostępu jako czytelnik lub pisarz (nie mówiąc już o funkcjach sprawdzania poprawności i innych funkcjach CouchDB), dzięki czemu mogą uzyskać dostęp tylko do podzbioru danych.
Drugie nieporozumienie polega na tym, że problem z crapsowaniem danych przez użytkownika! Jeśli użytkownicy otrzymają replikę bazy danych, mogą na niej zgarnąć wszystko, co lubią, bez wpływu na innych użytkowników. Ale powinieneś zweryfikować ich zmiany przed replikacją ich danych z powrotem do „centralnego” sklepu. Pomyśl o Git - użytkownicy mogą robić, co im się podoba, w oddziałach, rozwidleniach i lokalnych repozytoriach bez wpływu na gałąź główną. Połączenie z powrotem do mistrza wymaga dużo ceremonii i nie odbywa się na ślepo.
Buduję system obecnie korzystający z CouchDB, w którym użytkownicy muszą współpracować przy danych, aby zbudować zestaw danych, który jest następnie „publikowany” za pośrednictwem przepływu pracy QA / QC. Współpraca odbywa się na replice danych (nazywamy to tymczasową lub działającą bazą danych), a po zakończeniu osoba odpowiedzialna przeprowadza kontrolę jakości danych i dopiero po tym jest replikowana z powrotem do głównego repozytorium.
Wynika z tego wiele korzyści, które są trudne do osiągnięcia w innych systemach - jak kontrola wersji, replikacja i współpraca (niech działa offline!) Dla tradycyjnych trzypoziomowych aplikacji CRUD jest bardzo trudna.
Moja rada - jeśli Twoja aplikacja jest „tradycyjna”, zrób to w tradycyjny sposób. Jeśli którakolwiek z wyżej wymienionych rzeczy (choć jest o wiele więcej ...) dotyczy Ciebie, rozważ alternatywną architekturę i przygotuj się na późniejsze przemyślenia.
źródło
Myślę, że biorąc pod uwagę wszystkie twoje założenia, możliwe jest przejście bezpośrednio od klienta do bazy danych. Jednak uzasadnione jest sprawdzenie, czy twoje założenia są prawidłowe i prawdopodobnie tak pozostaną w przyszłości.
Martwiłbym się, że w przyszłości odczytanie wszystkich danych może nie być w porządku, a zwłaszcza, że w przyszłości może rozwinąć większą logikę biznesową. Oba są bardziej prawdopodobne, jeśli projekt zakończy się sukcesem.
Tak długo, jak dasz sobie radę z tymi problemami w przyszłości, i jeśli rzeczywiście będziesz musiał je rozwiązać, myślę, że twój projekt będzie działał. Myślę, że będziesz musiał bardzo uważać, aby rozdzielić obawy w kodzie JavaScript, a niektóre z nich mogą później zostać przepisane na serwerze.
Ale zdecydowanie mogłem zobaczyć, gdzie warto ryzykować, że zrobię to później, a korzyści wynikające z mniejszej liczby części ruchomych dzisiaj.
źródło
Przede wszystkim dziękuję za pytanie OUT OF THE BOX .... :)
Ale sugerowałbym to; Zawsze staraj się zachować segregację między 3 warstwami. które to Prezentacja / Biznes i Baza danych lub DAO, ponieważ będzie to najlepsza praktyka w tego rodzaju wymaganiach i konfiguracjach, w których każdego dnia będzie wiele zmian.
W prostych światach twoja warstwa prezentacji nie powinna wiedzieć o warstwie bazy danych, tzn. Format niektórych pól typu daty może różnić się od warstwy prezentacji i warstwy bazy danych, aby użytkownik miał swobodę wyboru odpowiedniego formatu daty zgodnie z własnymi potrzebami.
A Business Logic musi działać jak połączenie warstwy prezentacji z warstwą bazy danych / Dao, jak rzutowanie pól, niektóre walidacje biznesowe itp. Powinny być obsługiwane w warstwie biznesowej, a nie w sekcji Javascript, zgodnie z pytaniem.
Ta segregacja zapewni Ci dużą łatwość i wygodę podczas złożonych scenariuszy, funkcji, a nawet złożonych weryfikacji. Największą zaletą jest to, że możesz mieć różne technologie do wdrażania tych warstw i można je zmieniać zgodnie z potrzebami lub zakresem działalności.
Dzięki
źródło
Jeśli chcesz zbudować SQL w JavaScript i wysłać go do bazy danych, która weryfikuje prawa itp., Niż ze względów bezpieczeństwa byłaby to katastrofa. Po prostu dlatego, że kiedy budujesz API i sam tworzysz zapytania, musisz analizować z punktu widzenia bezpieczeństwa tylko ograniczoną liczbę zapytań. Jeśli zapytania są budowane poza systemem, masz potencjalnie nieograniczoną liczbę sztuczek, które ktoś może zrobić.
Ale tak nie jest, ponieważ korzystasz z bazy danych klucz-wartość (tak jak rozumiem, CouchDB ogólnie należy do tej kategorii). Sam interfejs bazy danych jest rodzajem warstwy środkowej i jest testowany ze względów bezpieczeństwa przez zespół Apache. Ze względu na stosunkowo prosty JavaScript API jest to jeszcze łatwiejsze do analizy pod kątem potencjalnych wad niż tak skomplikowane interfejsy, jakie mają aplikacje JSF.
Może to być bezpieczne rozwiązanie, jeśli wykonujesz złożone testy bezpieczeństwa. Może to być jeszcze łatwiejsze, niż w przypadku korzystania z frameworków takich jak JSF, które często używają za sobą mało czytelnego API. Bezpieczeństwo przez zaciemnienie nie jest uważane za rozwiązanie.
W odniesieniu do twojego pytania i tak nie będzie to bezpośredni dostęp do bazy danych. Bezpośrednim dostępem byłoby budowanie zapytań SQL w JavaScript (niestety, widziałem takie rozwiązania). W twoim przypadku sama CouchDB stanowi warstwę izolacyjną. Możesz oczywiście owinąć go w API, aby go wzmocnić, ale tak długo, jak możesz łatwo przetestować, co może zrobić konkretny użytkownik, i jeśli ograniczenia bezpieczeństwa działają dla Ciebie, będziesz mieć bezpieczne i solidne rozwiązanie bez dodatkowych warstw.
źródło
Widzę dwa problemy:
1. Tight Coupling: Zmienić opcję DB? Cóż, teraz musisz również zmienić cały kod po stronie klienta. Zaufaj mi. Nie potrzebujemy więcej problemów po stronie klienta.
2. Problem bezpieczeństwa TMI: zbyt wiele ujawnia, jak działają rzeczy. Auth może nadal stanowić przeszkodę, ale znalezienie exploita jest o wiele łatwiejsze, gdy dokładnie wiesz, co dzieje się po stronie serwera.
Bardzo, bardzo cienki poziom środkowy może być lepszym sposobem.
źródło
Klient nie może korzystać z aplikacji internetowej, jeśli javascript jest wyłączony (lub nie jest obsługiwany w przeglądarce jego urządzenia), jeśli javascript jest jedyną warstwą dostępu do bazy danych.
źródło