Sprawdzanie poprawności wprowadzania danych - gdzie? Ile? [Zamknięte]

28

Walidacja wprowadzania danych zawsze była dla mnie dość wewnętrzną walką.

Na progu dodania prawdziwej struktury bezpieczeństwa i kodu do naszego starszego projektu przepisania aplikacji (która do tej pory prawie utrzymuje mocny stary kod bezpieczeństwa i sprawdzanie poprawności danych), ponownie zastanawiam się, ile powinienem zweryfikować, gdzie itp

Przez 5 lat pracy jako profesjonalny programista Java stworzyłem i udoskonaliłem moje osobiste zasady dotyczące sprawdzania poprawności wprowadzania danych i środków bezpieczeństwa. Gdy chcę ulepszyć swoje metody, chciałbym usłyszeć od was kilka pomysłów. Ogólne zasady i procedury są w porządku, a także specyficzne dla Javy.

Podsumowując, są to moje wytyczne (dostępne w 3-warstwowym stylu aplikacji internetowej) z krótkimi objaśnieniami:

  • 1. strona klienta (przeglądarka): minimalna walidacja, tylko niezmienne reguły (obowiązkowe pole e-mail, należy wybrać jeden element i tym podobne); stosowanie dodatkowej walidacji, takiej jak „od 6 do 20 znaków” rzadziej, ponieważ zwiększa to prace konserwacyjne przy zmianach (można je dodać, gdy kod biznesowy jest stabilny);

  • Strona serwera pierwszego poziomu (obsługa komunikacji internetowej, „kontrolery”): Nie mam reguły dla tego, ale uważam, że należy obsługiwać tylko błędy manipulacji danymi oraz błędy montażu / analizy (pole urodzin nie jest prawidłową datą); dodanie tutaj dodatkowej weryfikacji sprawia, że ​​jest to naprawdę nudny proces;

  • 2. poziom (warstwa biznesowa): solidna walidacja, nie mniej; format danych wejściowych, zakresy, wartości, wewnętrzne sprawdzanie stanu, czy metoda nie może zostać wywołana w dowolnym momencie, role / uprawnienia użytkownika itd .; użyj jak najmniejszej ilości danych wejściowych użytkownika, w razie potrzeby pobierz je ponownie z bazy danych; jeśli weźmiemy pod uwagę pobrane dane z bazy danych również jako dane wejściowe, sprawdziłbym je tylko wtedy, gdy wiadomo, że niektóre dane są niewiarygodne lub wystarczająco uszkodzone w DB - silne typowanie wykonuje tutaj większość pracy, IMHO;

  • Trzecia warstwa (warstwa danych / DAL / DAO): nigdy nie uważałem, że potrzebna jest tutaj duża walidacja, ponieważ tylko warstwa biznesowa powinna mieć dostęp do danych (może to sprawdzić w niektórych przypadkach, np. „Param2 nie może być pusty, jeśli param1 jest prawdziwy”); zauważ jednak, że kiedy mam na myśli „tutaj” mam na myśli „kod, który uzyskuje dostęp do bazy danych” lub „metody wykonujące SQL”, sama baza danych jest zupełnie odwrotna;

  • baza danych (model danych): musi być tak przemyślana, silna i samowykonująca, aby w jak największym stopniu unikać niepoprawnych i uszkodzonych danych w bazie danych, z dobrymi kluczami głównymi, kluczami obcymi, ograniczeniami, typem danych / długością / rozmiarem / precyzja i tak dalej - nie uwzględniam wyzwalaczy, ponieważ mają oni swoją prywatną dyskusję.

Wiem, że wczesna walidacja danych jest przyjemna i pod względem wydajności, ale powtarzana walidacja danych jest nudnym procesem i przyznaję, że sama walidacja danych jest dość denerwująca. Dlatego tak wielu programistów pomija go lub robi to w połowie. Ponadto każde zduplikowane sprawdzanie poprawności jest możliwym błędem, jeśli nie są one synchronizowane przez cały czas. To są główne powody, dla których obecnie wolę pozwolić większości walidacji na warstwę biznesową, kosztem czasu, przepustowości i procesora, wyjątki obsługiwane osobno dla każdego przypadku.

Więc, co o tym myślisz? Przeciwne opinie? Czy masz inne procedury? Odniesienie do takiego tematu? Każdy wkład jest ważny.

Uwaga: jeśli myślisz o robieniu rzeczy w Javie, nasza aplikacja jest oparta na Spring z Spring MVC i MyBatis (wydajność i zły model bazy danych wykluczają rozwiązania ORM); Planuję dodać Spring Security jako naszego dostawcę zabezpieczeń oraz JSR 303 (Hibernate Validator?)

Dzięki!


Edycja: dodatkowe wyjaśnienia na 3. warstwie.

mdrg
źródło
Moja rada to przestudiowanie działania Hibernacji Walidatora. Nie uważałem, że JSR 303 jest przydatny, ponieważ sprawdzanie poprawności rozpoczyna się podczas wytrwałości, podczas gdy niektóre moje reguły musiały być egzekwowane dużo przed wytrwałością, ponieważ miałem reguły biznesowe, które polegały na podstawowej weryfikacji. Moim zdaniem działa to dla bardzo zamkniętego modelu; może używałem go niepoprawnie, ale nigdy nie znalazłem nikogo z doświadczeniami innymi niż moje.
Vineet Reynolds
@Vineet Reynolds Już go użyłem do sprawdzania poprawności formularza w Spring MVC, to naprawdę świetne połączenie. Dostaję weryfikację po stronie serwera z precyzyjnymi komunikatami bez większego wysiłku, odpowiedni błąd wyświetlany użytkownikowi. Nadal mam go przetestować całkowicie na obiektach po stronie serwera, nie jestem pewien zalet. Spójrz na ten przykładowy post, właśnie tak go wykorzystałem: codemunchies.com/2010/07/07/m
mdrg
2
umieścić zbyt wiele walidacji. EveryWhere cholera te dane wejściowe użytkownika @ #! ! @@!
Chani

Odpowiedzi:

17

Twoja weryfikacja powinna być spójna. Jeśli więc użytkownik wprowadzi pewne dane w formularzu internetowym, które zostały określone jako poprawne, warstwa bazy danych nie powinna zostać odrzucona z powodu niektórych kryteriów, których nie wdrożono po stronie klienta.

Jako użytkownik nic nie byłoby bardziej irytujące niż wprowadzenie strony danych, która najwyraźniej jest poprawna, ale po znacznej podróży do bazy danych zostanie poinformowana, że ​​coś jest nie tak. Byłoby to szczególnie prawdziwe, gdybym w tym procesie potknął się o weryfikację klienta.

Musisz mieć sprawdzanie poprawności na różnych poziomach, ponieważ je ujawniasz i potencjalnie nie masz kontroli nad tym, kto je wywołuje. Musisz więc ustalić (tak dalece, jak to możliwe), aby twoja walidacja została zdefiniowana w jednym miejscu i wywołana z dowolnego miejsca. Sposób organizacji zależy od języka i struktury. W Silverlight (na przykład) możesz go zdefiniować po stronie serwera, a przy użyciu odpowiednich atrybutów zostanie on skopiowany po stronie klienta i tam użyty.

ChrisF
źródło
2
+1 Absolutnie. Chciałem powiedzieć to samo o ASP.NET MVC, ale pobiłeś mnie. :) Naprawdę, POTRZEBUJEMY tylko sprawdzania poprawności na miejscu, aby upewnić się, że system pozostaje w prawidłowym stanie. Reszta walidacji, podobnie jak po stronie klienta, ma na celu zwiększenie użyteczności i czasu zmarnowanego przez użytkownika, dlatego powinno to być najważniejsze. Spójność jest kluczem.
Ryan Hayes
2
Jeśli chodzi o „podróż w obie strony”, nie widzę problemu, dopóki strona zostanie ponownie załadowana z odpowiednimi komunikatami o błędach i wszystkie pola zostaną wypełnione tym, co wcześniej wpisałeś (większość interfejsów nie spełnia tego ostatniego szczegółu). Jeśli powrót z błędami trwa zbyt długo, oznacza to, że jest to kandydat do dodatkowej weryfikacji po stronie klienta.
mdrg
I oczywiście, jeśli weryfikację można łatwo powielić w aplikacji, nie ma powodu, aby to marnować. Po stronie serwera jest to łatwe, ale po stronie klienta, bez takich narzędzi sprawdzania poprawności, jak te, o których wspomniałeś, staje się bardzo frustrujące (np. Pisanie dużej ilości kodu sprawdzania poprawności JS, tak jak napisałeś na serwerze) .
mdrg
10

W systemie relacyjnym postrzegam to jako podejście trójwarstwowe. Każda warstwa jest ograniczona przez poniższe:

  • Prezentacja / interfejs użytkownika
    • prosta weryfikacja danych wejściowych
    • nie kontynuuj, jeśli dane wejściowe mają niewłaściwy format
    • „brama” żądań klienta do serwera w celu zmniejszenia liczby podróży w obie strony, dla lepszej użyteczności i zmniejszonej przepustowości / czasu
  • Logika
    • logika biznesowa i autoryzacja
    • nie pozwól użytkownikom robić rzeczy, których nie wolno im robić
    • obsłużyć właściwości „pochodne” i podać tutaj stan (rzeczy, które byłyby denormalizowane w bazie danych)
  • Dane
    • podstawowa warstwa integralności danych
    • absolutnie nie przechowuj żadnych śmieci
    • sama baza danych wymusza formaty danych (int, data itp.)
    • stosuj ograniczenia bazy danych, aby zapewnić prawidłowe relacje

Idealną odpowiedzią na to będzie to system, który pozwala zdefiniować ograniczenia na wszystkich trzech warstw w jednym miejscu. Wymagałoby to pewnego wygenerowania kodu dla SQL i przynajmniej pewnej weryfikacji danych dla klienta i serwera.

Nie wiem, czy jest tu jakaś srebrna kula ... ale ponieważ jesteś na JVM, sugerowałbym, aby spojrzeć na Rhino, aby przynajmniej udostępnić kod weryfikacyjny JavaScript między klientem a serwerem. Nie pisz dwa razy sprawdzania poprawności danych wejściowych.

John Cromartie
źródło
Rzucę okiem na Rhino. Jeśli można go w jakiś sposób zintegrować ze sprawdzaniem poprawności formularzy Spring MVC, to o wiele lepiej.
mdrg,
8

• Trzecia warstwa (warstwa danych / DAL / DAO): nigdy nie uważałem, że potrzebna jest tutaj duża walidacja, ponieważ tylko warstwa biznesowa powinna mieć dostęp do danych (może to być poprawne w niektórych przypadkach, np. „Param2 nie może być pusty, jeśli param1 jest prawdziwy”) .

To takie złe. Najważniejszym miejscem do weryfikacji jest sama baza danych. Na dane prawie zawsze ma wpływ więcej niż aplikacja (nawet jeśli uważasz, że tak nie będzie), a w najlepszym wypadku nieodpowiedzialne jest niewprowadzanie odpowiednich kontroli do bazy danych. Decyzja o nieprzestrzeganiu tego powoduje większą utratę integralności danych niż jakikolwiek inny czynnik. Integralność danych ma kluczowe znaczenie dla długoterminowego korzystania z bazy danych. Nigdy nie widziałem żadnej bazy danych, która nie egzekwowałaby reguł integralności na poziomie bazy danych, która zawierałaby dobre dane (i widziałem dane w dosłownie tysiącach baz danych).

Mówi to lepiej niż ja: http://softarch.97things.oreilly.com/wiki/index.php/Database_as_a_Fortress

HLGEM
źródło
Zgadzam się z ostatnim fragmentem tego artykułu, chyba nie wyraziłem się jasno w tej części. Zaktualizowałem pytanie o dalsze szczegóły. Dzięki!
mdrg
2

Wszystkie powyższe założenia zakładają, że programiści i opiekunowie są doskonali i piszą idealny kod, który zawsze działa idealnie. Przyszłe wersje oprogramowania znają wszystkie założenia, które poczyniłeś i których nigdy nie udokumentowałeś, a także użytkowników i hakerów, którzy wprowadzają dane do systemu w sposób, jakiego nigdy sobie nie wyobrażałeś.

Pewnie, zbyt duża walidacja jest złą rzeczą, ale zakładając, że programy, sieci i systemy operacyjne są idealne, hakerzy nie dostaną się przez twoją zaporę, DBA nie będą ręcznie „poprawiać” bazy danych, prawdopodobnie jest gorsza.

Narysuj okręgi graniczne wokół rzeczy, zidentyfikuj tryby awarii, przed którymi chroni, i zastosuj odpowiedni poziom sprawdzania tej granicy. Na przykład twoja baza danych nigdy nie powinna widzieć nieprawidłowych danych, ale jak to się mogło stać, a co jeśli? Kto jest twoim użytkownikiem, jaki jest koszt awarii?

Studiuj modele bezpieczeństwa świata fizycznego, bezpieczeństwo powinno być warstwowe, jak cebula. Jedna gruba ściana jest uważana za słabe bezpieczeństwo. Sprawdzanie poprawności danych należy traktować w ten sam sposób.

mattnz
źródło
1

Dwie krótkie ogólne zasady walidacji:

Jeśli zamierzasz zadzwonić na coś, co nie gwarantuje, że coś zwróci (błąd, wyjątek), aby poinformować Cię o nieprawidłowych danych wejściowych w sposób, który możesz przekazać z powrotem dzwoniącemu, sprawdź to.

Jeśli zamierzasz robić cokolwiek innego z danymi (podejmować decyzje, matematyki, przechowywać je itp.), Sprawdź je.

Blrfl
źródło