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.
Odpowiedzi:
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.
źródło
W systemie relacyjnym postrzegam to jako podejście trójwarstwowe. Każda warstwa jest ograniczona przez poniższe:
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.
źródło
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
źródło
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.
źródło
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.
źródło