Techniki Zaawansowane
8 godz. 35 min · Java · Full-stack i Programowanie
Rafał SolarskiW poczatkowych lekcjach przyjrzymy sie pokladowi, na jakim bedziemy uruchamiali nasze programy. Wykorzystamy VisualVM do podgladania parametrów JVM. Zobaczymy równiez jakie zasoby sa tam dostepne oraz dowiesz sie jak monitorowac to, czy dobrze z nich korzystamy. Opowiemy Ci tez miedzy innymi o tym, jak zrobic heap i thread dump, oraz jak wlaczyc logi GC.
Kolejne lekcje kursu zostaly poswiecone wyrazeniom regularnym. Wyrazenia regularne mozemy wykorzystac nie tylko do walidacji danych wprowadzania przez uzytkownika, ale równiez do dzielenia tekstu oraz wyluskiwania wystapien wzorców w duzym tekscie. W tym rozdziale dowiemy sie miedzy innymi tego, jak mozemy wykorzystac ten potencjal z poziomu Javy.
Dzieki typom generycznym jestesmy w stanie osiagnac bezpieczenstwo typów w trakcie kompilacji przy zachowaniu elastycznosci pisanego kodu. W nastepnym rozdziale kursu przyjrzymy sie temu, jak mozemy je wykorzystac, oraz w jaki sposób czasami nalezy z tego bezpieczenstwa zrezygnowac.
Interfejsy funkcyjne to sposób na przeniesienie odrobiny swiata programowania funkcyjnego do Javy. Gdy polaczymy je z wyrazeniami lambda oraz API strumieni pozwola nam pisac te sama logike w duzo bardziej przejrzysty sposób.
Kolekcje, czyli listy, mapy, zbiory i kolejki to jedne z najczesciej wykorzystywanych klas w codziennej pracy. To jak dobrze poznamy ich mozliwosci ma ogromny wplyw na to, w jaki sposób bedziemy podchodzili do rozwiazywania wyzwan na naszej drodze.
System plików to zasób bez którego ciezko sobie poradzic. Pozwalaja nam na dostarczanie konfiguracji, danych wejsciowych i wyjsciowych, a przez to równiez integrowanie ze soba calych systemów.W tym rozdziale nauczymy sie korzystac z tych dobrodziejstw w bezpieczny sposób wykorzystujac m.in. IO Streams.
Trzymanie daty w String to niekoniecznie najwygodniejszy sposób. Juz od pewnego czasu Java dysponuje bardzo wygodnym Date&Time API - zobaczymy, co mozemy w nim znalezc.
Wielowatkowosc nie jest prosta... i dlugo tak jeszcze pozostanie. Nawet jesli korzystamy z frameworków, które próbuja ja przed nami ukryc, to ciagle musimy byc swiadomi problemów jakie sie z nia wiaza. W tym rozdziale poznamy glówne problemy na jakie mozna natrafic programujac wielowatkowo w Javie. Poznamy równiez klasy, które zdecydowanie pomoga nam zapanowac nad ta zlozonoscia.
JDBC to najbardziej podstawowy sposób laczenia sie z baza SQL z poziomu Javy. W wielu systemach/aplikacjach stosuje sie rozwiazania ORM takie jak JPA/Hibernate. Mimo wszystko warto wiedziec jak to pod spodem dziala oraz umiec poradzic sobie w aplikacjach, gdzie wybrano bardziej "lekkie" podejscie niz Hibernate.
Na koniec kursu wykorzystamy zdobyta wiedze, aby stworzyc prosta aplikacje pozwalajaca na przechowywanie danych o wydatkach. Po stworzeniu coreu aplikacji, mozesz spróbowac uzupelnic go za pomoca GUI.
Ten kurs stworzony zostal przede wszystkim z mysla o osobach, które juz poznaly podstawy jezyka, takie jak zmienne, mechanizmy kontroli wykonania, klasy, typy generyczne.Jezeli chcesz poczuc sie swobodnie nie tylko jesli chodzi o mechanizmy jezyka, ale równiez pod wzgledem znajomosci standardowej biblioteki Javy - to kurs w sam raz dla Ciebie. Materialy beda przydatne dla studentów, którzy znaja juz podstawowa skladnie Javy; programistów Javy chcacych poszerzyc lub uporzadkowac swoja wiedze; programistów innych jezyków, którzy chca poznac inny stack technologiczny.
Cześć w tej lekcji pokażę ci jak wykorzystywać prepared
statement jest to tak trochę powiedzmy ulepszona wersja statement która
pozwoli nam przeciwdziałać między innymi jednemu z najpopularniejszych ataków
jakim jest sql injection też zaprezentuje jak go przeprowadzić
mniej więcej na jednym przykładzie oraz później zobaczymy jak wykorzystywać
też ten prepared statement do wrzucania kolekcji danych oraz
jak to robić w sposób batch'owy tutaj mamy taki przykład w którym powiedzmy
on jest trochę przerobiony w stosunku do poprzedniej lekcji ale zasadniczo mamy jakiś fragment
który służy za przygotowanie danych tak mamy dwie tabele tabela
employees zniknęła jest teraz employees nodes i tajemnicza
tabela o tajemniczej nazwie secrets tutaj do employees nie
ma żadnych danych będziemy zaraz wrzucać a w tabeli secrets jest jakaś
tajemna powiedzmy dana ta która jest bardzo ważna i nie może zniknąć
nie może ujawnić się tak okej i tutaj powiedzmy
po wrzuceniu tych danych mamy work on db tutaj możemy mieć taki template tak
do pracy okej i mamy takie wymaganie dostajemy
skądś jakąś daną no powiedzmy jest to fragment jakiejś notki
jakiegoś pracownika którą musimy wrzucić bezpiecznie do naszej tabelki
no i tutaj sobie tworzymy po prostu create statement no i tutaj
sklejamy tak bezczelnie trochę to zapytanie tak
powiedzmy podaje mi jeszcze tutaj trzeba tragicznie wygląda to formatowanie
no i się tutaj po prostu wrzuca teraz tego stringa pomiędzy
tak i on tam powiedzmy ląduje teraz w tej bazie może coś zobaczyć
jak to wygląda tak w ten sposób i okej i zasadniczo
to działa tak i teraz zastanówmy się te dane one
mogą przychodzić z jakiegoś front endu tak jakiejś powiedzmy konsoli użytkownika i
ten użytkownik może niekoniecznie mieć dobre intencje tak powiedzmy to jest jakiś
system jakiś sass coś takiego tak i wielu użytkowników pracuje na przykład
na tej aplikacji i niektórzy z nich mogą na przykład chcieć wyciągnąć jakieś dane
z naszego systemu zrobić po prostu krzywdę tym danym tak zastanówmy
się czy to jak to jest to sklejane to jest najbezpieczniejszy sposób czy użytkownik nie
może nam w tym momencie zagrozić tak no niby tutaj się otwierają
ciapki tak no i to trafia jako w środku ma
teoretycznie być jakimś ciągiem znaków które po prostu trafią
do tego pola tak jak się okazuje w przypadku podstawienia takich
danych jeżeli użytkownik wprowadzi nam coś takiego to teraz
nasze zapytanie nie do końca jest takie bezpieczne bo zobaczymy że w wyniku jego
działania tutaj do tabeli employees nodes trafił
wynik tego co się znajdowało w tym secrets tak no i
to nie jest najfajniejsze z tego względu że powiedzmy to
jest notka tego użytkownika i pewnie on ma do nich dostęp na przykład
może je sobie gdzieś wyświetlić no i teraz on sobie wyświetli notkę a tam w środku patrzy
o jest hasło do czegoś na przykład nie no nie jest to najfajniejszy
sposób zobaczmy teraz w ogóle co to się wydarzyło że to tak tak udało
się to jakoś tak zhakować tak no tutaj jak mieliśmy otwierającą ciapkę
tak może sobie wyprintujmy w ogóle jak działa teraz jak
końcowo wygląda to wyrażenie o to koniec końców
po sklejeniu to wyrażenie wygląda w ten sposób i teraz tak tutaj w values
tak robimy insert into tak tę zmienną znaczy w te
kolumnę wrzucamy takie dane które są wynikiem powiedzmy tego tutaj no
i tutaj był otwierany powiedzmy ciąg
znaków ale od razu został zamknięty tak tą ciapką tym apostrofem
tutaj został wrzucony no i później jest operator konkatenacji tak
czyli powiedzmy sklejanie ze sobą dwóch ciągów znaków no
i później jest coś co się nazywa select czyli powiedzmy wyciągnięcie
wynikiem teraz co tu zostanie doklejone to jest wynik takiego selectu
takiego zapytania jakie tutaj mamy no i tu już mamy zapytanie takie
bezczelne po prostu o te dane które są w tej w
tej kolumnie tutaj w innej zupełnie tabeli tak ono oczywiście tutaj jest jakiś
max na tym jakiś group by i po to żeby ominąć kilka rzeczy żeby to w ogóle
tutaj wepchnąć jako powiedzmy pod zapytanie w insercie
no ale taką rzecz czy da się zrobić no i to nie jest tak że
sqlite jest powiedzmy jakiś taki bardzo ubogi i
powiedzmy nie stanie sobie z tym radzić ale po prostu na większości baz takie
coś da się zrobić w momencie kiedy my sobie sklejamy tak jakby
to zapytanie tego inserta razem z danymi które
nam po prostu podstawia użytkownik to w większości sytuacji da
się to tak zapisać tak dobrać te dane wejściowe aby
coś wyciągnąć tak później pytanie czy tam gdzie my to sobie wkleimy to czy
użytkownik ma dostęp tam tak no może być też
tak że użytkownik na przykład my robimy select i jako select
którego wynik zwrócimy użytkownikowi wstawiamy też fragment od użytkownika
na przykład jakiegoś id czy jakiś nazwę czegoś i
później zwracając dane użytkownika on tam w tym parametrze
jednym który tam wstawił właśnie opędzlował powiedzmy te rzeczy
związane na przykład właśnie z tym że to jest wstawione gdzieś i dotknął jeszcze jakiegoś
sub selecta jakieś podzapytanie tak w którym wyciągnął więcej danych
niż ma uprawnienia do oglądania tak no więc takie właśnie sklejanie
string do stringa z tym co dostajemy od użytkownika nie jest
najlepszym sposobem tak nie jest najbezpieczniejsze możemy
sobie z tym poradzić wykorzystując coś to się nazywa prepared statement i jego parametry
okej będzie to wyglądało w ten sposób tak jak wcześniej tworzyliśmy statement tak
tutaj to teraz stworzymy prepared statement one to sobie dziedziczą ale chcemy
mieć prepared statement ponieważ on ma szersze powiedzmy metody tak teraz
ten sql który tutaj podajemy on w środku może zawierać powiedzmy
w tym miejscu gdzie wcześniej wklejaliśmy ten node provided by user
teraz mamy znak zapytania i to jest powiedzmy taki case
holder na parametr który my wstawimy 1 parametry my umieszczamy
w tym miejscu tak statement set string tutaj podajemy indeks
liczony od jedynki w którym mamy umieścić tak bo tutaj możemy mieć wiele
tych znaków zapytania w którym mamy umieścić powiedzmy ten parametr no
i później robimy execute update i teraz zobaczymy czy to się nam
zmieni w stosunku do tego co było do tej pory jak widzimy do tej tabelki
employees nodes teraz jako value nie trafił już wynik
zapytania tego maxa secrets tylko
trafiło teraz po prostu to zapytanie tak czyli ono w postaci takiego właśnie ciągu
znaków z czego to wynika to wynika z tego że tutaj jak robimy set string
to wrzucamy prepared statement zanim uruchomi tego
powiedzmy update'a na bazie danych on escape'uje
z niego powiedzmy te rzeczy które są w tych w tych parametrach czyli
jeżeli na przykład tutaj jest apostrof tak jakieś rzeczy powiedzmy takie które
mogłyby sprawić że ten otwarty dopiero tutaj dla
tego typu tak jak tutaj miałem ten apostrof na początek i na końcu
ponieważ rozkład wymaga żeby tekst do niego wrzucać właśnie w takich
ciapkach tak no to jeżeli w tym parametrze który
my tutaj podajemy są takie znaki które dla danego typu czyli
w tym momencie stringa sprawiłyby że ten string byłby powiedzmy
właśnie zakończone byłoby byłoby
bezterminowany ten ciąg znaków tak po prostu to jest escape'owalne
odpowiedzio tak ileś takich niebezpiecznych znaków jest escape'owanych po prostu jest przed
nimi dostawiany odpowiedni symbol który jego escape'uje całość
tak wyescape'owana tutaj nam trafiła do tego i to już powiedzmy
nie było niebezpieczne dla nas po prostu cały ten ciąg który
wkleiliśmy on trafił do tabelki do kolumny i teraz z tym się raczej nic nie
stanie tak przynajmniej nie wywoła tej akcji której o którą się my się baliśmy skoro
jesteśmy przy prepeared statement to poza tym że ono może nam
służyć do zabezpieczania się przez sql injection czyli
właśnie temu atakowi który pokazałem przed chwilą to jest też ono fajne jeżeli
chcemy powiedzmy mieć jakiś template tak jak tutaj mieliśmy tak go
możemy sobie wrzucić na przykład jako jakiś constant w naszej klasie i
tylko odpowiednio go parametryzować czyli możemy go na przykład reużywać
ale poza tym że możemy sam template reużywać to już jeżeli
on jest wrzucony do prepared statement tak czyli jest już utworzona
powiedzmy prezentacja w klasie tak na tej prezentacji możemy
używać wiele razy tak tak mieliśmy tam executive update na
zwykłym statemencie tutaj tak samo i za każdym razem możemy podstawić inny parametr
czyli to się świetnie nadaje na przykład do wrzucania całej
kolekcji obiektów tutaj tworzę sobie note'y tak powiedzmy te notatki
użytkownika a tworzy je powiedzmy w taki łatwy sposób po prostu doklejem
do note kolejne kolejne liczby od 1 do 9
tak teraz jak to sobie odpalimy to nam się wszystko wrzuci tutaj tak
i teraz tak jakby co się wydarzyło to tutaj wszystko
to co teraz odpaliliśmy execute update to wyglądało tak że bierzemy sobie ten
prepared statement podmieniamy powiedzmy ten place holder tak
leci update i w tym momencie jest stuknięcie do bazy danych
tak w momencie kiedy mamy tutaj sqlite tak
to nas to nie boli ponieważ ten plik raczej leży u nas chyba że
jest na jakimś takim jakimś dysku sieciowym który do którego dostęp nie
jest taki szybki ale raczej w naszym przypadku to jest
prawie błyskawiczne tak powiedzmy też dla takiej ilości danych
które teraz wrzucamy to jest powiedzmy okej gdybyśmy
jednak chcieli wrzucać dużo danych na raz i nie chcielibyśmy
żeby za każdym powiedzmy każdym wierszem który wrzucamy szedło stuknięcie
do baz danych możemy z tego zrobić batch i do tego też możemy
właśnie użyć prepared statement po prostu tutaj
na początku robimy add batch tak i teraz to co tutaj
zostało uzupełnione tak jakby ta migawka tego prepared
statement na ten moment jest dodawana jako jeden wiersz do batch'a
a na koniec możemy jeszcze zrobić execute batch tak
czyli tutaj ładujemy do bachata tak ileś
tam wierszy w tym momencie 10 tak czy 9 nawet i
na koniec one powiedzmy jest robione okej teraz dopiero
stuknij do bazy i teraz on na raz zwróci nam 9 wierszy tak to
działa dokładnie tak samo i wygląda tak samo a pod spodem tak jakby oszczędzamy
trochę na połączeniu z bazą danych connection może być jedno tak połączenie
jedno w tym wypadku to nawet nie ma z sqlite większego
znaczenia ale też tak jakby liczba rozpoczynanych
kolejnych powiedzmy wysyłek tych danych tak tych
insertów jest mniejsza tak powiedzmy wrzucamy na przykład możliwe
że pod spodem leci mniejsza liczba pakietów tcp chociaż tak więc
jest to wydajniejsze po prostu przy 10 9 powiedzmy nie zobaczymy
różnicy ale przy powiedzmy wrzucaniu dużej liczby tych rekordów tysięcy tak na
pewno wydajność się poprawi okej to wszystko co chciałem ci pokazać w
kontekście prepared statement dzięki wielkie i do zobaczenia