Archiwa tagu: spring boot

Spring Boot: Bezpieczeństwo 101

Pora zabezpieczyć stronę – niektóre jej części chcę pokazywać tylko zalogowanym użytkownikom.

Ukrycie całej strony za hasłem

Ukrycie całej strony za hasłem jest wyjątkowo proste. Wystarczy dodać do pom.xml następującą zależność:

Strona wygląda wtedy tak:

Cała strona ukryta za hasłem
Cała strona ukryta za hasłem

Skąd wiem, jakiego podać użytkownika i hasło?

  • Jeśli nic dodatkowo nie konfigurowałam, mogę zalogować się przy użyciu nazwy użytkownika User oraz hasła zapisanego w logach serwera:
  • Mogę też podać dane logowania w pliku application.properties:

Zabezpieczenie na poziomie stron i metod

Dodaję do swojego kodu następującą klasę konfiguracyjną:

W metodzie configureAuth uzyskuję dostęp do obiektu AuthenticationManagerBuilder i definiuję parę użytkowników i nadajemy im role (użytkownika lub administratora).

W metodzie configure podaję, kto ma mieć dostęp do której części aplikacji. I tak:

  • Do adresów wymienionych w linii 17 dostęp mają wszyscy, a więc nie tylko zalogowani użytkownicy.
  • (18) Do stron pod adresem /admin i poniżej dostęp ma tylko użytkownik o prawach administratora.
  • (19) Do stron pod adresem /user i poniżej dostęp ma tylko użytkownik w roli USER.
  • (20) Do reszty stron dostęp mają tylko zalogowani użytkownicy, niezależnie od roli.
  • Włączam dodatkowo standardowy formularz logowania (21) i ustawiam adres / jako domyślne miejsce lądowania po udanym zalogowaniu bądź wylogowaniu.

Dodam jeszcze następujący fragment kodu do mojego szablonu strony:

Uwaga! Żeby silnik szablonów Thymeleaf odpowiednio przetworzył ten fragment, w pom.xml muszę dodać zależność do artefaktu thymeleaf-extras-springsecurity4.

Jak to wygląda na stronie?

Strona główna, niewymagająca logowania
Strona główna, niewymagająca logowania
Standardowy formularz logowania
Standardowy formularz logowania
Użytkownik zalogowany
Użytkownik zalogowany

Dodatkowo mogę definiować wymagania bezpieczeństwa w kodzie, przy każdej metodzie kontrolera, np.:

Kod jest dostępny w GitHubie.

Co dalej?

Czasami coś idzie nie tak… Moja własna strona błędu

Nadal w ramach Daj się poznać.

Podobny obrazek widział chyba każdy programista aplikacji webowej. Od czasu do czasu serwer Tomcat postanawia poinformować użytkownika aplikacji, że coś poszło nie tak. Informuje dość brutalnie, przynajmniej od strony stylistycznej. Co gorsza, przy okazji potrafi wyjawić przypadkowemu użytkownikowi dość dużo informacji na temat wnętrza programu.

Informacja o błędzie wygenerowana przez serwer Tomcat. W tym wypadku żądana strona nie istnieje.
Informacja o błędzie wygenerowana przez serwer Tomcat. W tym wypadku żądana strona nie istnieje. Czasami można w tym miejscu zobaczyć ciekawszy materiał, czyli stack trace.

Tego typu informacje przydają się do debugowania aplikacji na etapie jej powstawania, ale użytkownik końcowy nie powinien ich oglądać (chociażby z powodów estetycznych).

Jak sobie z tym poradzić? Framework Spring Boot automatycznie ustawia dla nas nieco tylko ładniejszą stronę błędu:

Whitelabel Error Page, czyli strona błędu generowana przez Spring Boot
Whitelabel Error Page, czyli strona błędu generowana przez Spring Boot

Mechanizm ten można wyłączyć we właściwościach aplikacji (application.properties):

Także zmiana domyślnego ViewResolver może usunąć tę wersję informacji o błędzie i przywrócić wersję tomcatową.

Jeśli zamiast strony prezentowanej przez Springa chcesz ustawić swoją własną, musisz zerknąć do dokumentacji wybranego przez Ciebie silnika szablonów. W przypadku Thymeleaf wystarczy dodać szablon o nazwie error.html:

Szablon błędu dla silnika Thymeleaf
Szablon błędu dla silnika Thymeleaf

Dzięki temu strona błędu może wyglądać na przykład tak:

error

Czy jest ładniejsza… Pozostawiam ocenie Czytelnika 😀

Wdrażam moją aplikację (która nadal nic nie robi) w chmurze Pivotal Web Services

Co to za aplikacja?

W ramach konkursu Daj się poznać pracuję nad aplikacją Szafbook, na którą pomysł został naszkicowany tutaj. Moim celem jest przede wszystkim nauczenie się nowych rzeczy, dlatego sama aplikacja solidnie kuleje i, jak w tytule, naprawdę nic jeszcze nie robi. Ale już da się wdrożyć!

Co to jest Pivotal Web Services?

Pivotal to firma z, oczywiście, San Francisco. Jeden z jej produktów to chmura i oprogramowanie Pivotal Cloud Foundry . Pivotal Web Services to ich instancja dostępna publicznie. Umożliwia łatwe wdrażanie aplikacji napisanych w następujących językach i frameworkach: Java, Grails, Play, Spring, Node.js, Ruby on Rails, Sinatra, Go.

Zachęcająca grafika ze strony Pivotal Web Services
Zachęcająca grafika ze strony Pivotal Web Services

Moja aplikacja jest napisana w Spring Boot. A więc do dzieła!

Jak wdrożyć aplikację?

  1. Wchodzimy na stronę http://run.pivotal.io/. Wita nas przyjazny komunikat o 87 dolarach w prezencie od firmy na cele testowania.

    1
    Bierzemy!
  2. Rejestrujemy się w serwisie. Musimy podać numer telefonu, żeby przepisać otrzymany kod.
  3. Firma uprzejmie prowadzi nas za rękę. Teraz pora na instalację PWS CLI, czyli konsoli do zarządzania aplikacją. Po instalacji logujemy się w sposób pokazany na stronie. 2
  4. Wdrażamy!

  5. Podglądamy efekt na stronie.

    Wdrożone!
    Wdrożone!
  6. Uczymy się korzystać z konsoli tekstowej oraz z widoku www.

Ile to kosztuje?

Cena to $0.03 za GB RAM na godzinę. Na stronie http://run.pivotal.io/pricing/ mamy wygodny suwak do obliczania kosztów:

Szacunkowe koszty utrzymania aplikacji
Szacunkowe koszty utrzymania aplikacji

$87 dostałam za darmo, na chwilę powinno wystarczyć.

Co dalej?

Przydałoby się to wdrażać automatycznie z GitHuba przez jakiś serwer ciągłej integracji.

PS.

  1. Dziękuję Marcinowi M. za podpowiedzi dotyczące wdrożenia w komentarzach pod pierwszym wpisem konkursowym.
  2. Poświęciłam wcześniej chwilę na rozpoznanie chmury OpenShift, ale dokumentacja była (dla mnie) znacznie mniej czytelna.

 

 

Mobilna wersja strony w Spring Boot

Moja konkursowa aplikacja właściwie nic jeszcze nie robi – ot, wyświetla kilka widoków. Dzisiaj przetestowałam nowy drobiażdżek: wyświetlanie innej wersji strony na urządzeniach mobilnych.

Jak to zrobić? W Spring Boot to naprawdę prosta sprawa. Wystarczy:

  1. Dodać jedną zależność w pliku pom.xml
  2. Dopisać poniższą linię w pliku resources/application.properties (utworzyć plik, jeśli nie istnieje), nadpisując tym samym domyślnie ustawienie właściwości.
  3. Zapisać mobilne wersje widoków w katalogu mobile (lub innym, jeśli zmienisz domyślną wartość właściwości spring.mobile.devicedelegatingviewresolver.mobilePrefix)

    Mobilne wersje widoków
    Mobilne wersje widoków

Po takim przygotowaniu możemy już podziwiać stronę w wersji normalnej i mobilnej. W swojej wersji mobilnej na teraz dodałam tylko słówko “MOBILE”. Wygląda to tak:

Wersja mobilna strony

Urządzenie mobilne udałam przy użyciu dość badziewiastego dodatku do Firefoksa o nazwie User Agent Switcher.

UPDATE: Marcin S. podpowiedział mi, że w Chrome można udawać urządzenie mobilne bez potrzeby instalowania żadnych dodatków:

Tryb mobilny w Google Chrome

UPDATE2: Historie komórkowe

Odkrywam nową Javę przy okazji dat

Przyznaję, że ten wpis jest nieco wymuszony. Zasady Daj się poznać nakładają na mnie obowiązek wrzucania dwóch postów konkursowych tygodniowo. Tymczasem, choć informatycznie działo się u mnie sporo, projekt konkursowy w tym tygodniu leżał odłogiem. Dlaczego? Pomijając już przygody z nadgarstkiem – rozpoczęłam studia podyplomowe (przetwarzanie danych – big data)!  Wczoraj, na moim dawnym wydziale, bawiłam się SQL-em, dzisiaj R. O R mam nawet anegdotę, ale na razie nie wymyśliłam pretekstu, żeby podciągnąć ją pod temat konkursowy.

Jeśli chodzi o moją aplikację Szafbook: nadal gnębi mnie kwestia dat. Pisałam już o tym, że HTML5 udostępnia pole wejściowe input typu date.  Niektóre przeglądarki (Chrome!) wyświetlają przy nim elegancki widżet do wyboru daty z kalendarza. Inne nadal pozwalają/nakazują użytkownikowi samodzielne wpisanie wartości.

Nie byłam pewna, co z tym zrobić. Nie chcę rozbijać daty urodzenia na trzy osobne pola – za bardzo podoba mi się rozwiązanie z Chrome. Nie chcę wykrywać przeglądarki i podejmować decyzji w zależności od niej. Tak długo, jak będzie to możliwe, chcę się trzymać z dala od JavaScriptu.

Co tymczasowo wymyśliłam? Własny sposób tworzenia obiektu reprezentującego datę na podstawie danych wprowadzonych przez użytkownika, w  którym pozwalam użytkownikowi na nieco większą elastyczność niż trzymanie się jednego sztywnego formatu daty.

Kod i uwagi do niego wklejam poniżej. Przy okazji zauważyłam kilka nowych (dla mnie) rzeczy w Javie. Najbardziej spodobały mi się grupy nazwane w wyrażeniach regularnych, wprowadzone w Javie 7.  Dzięki ich istnieniu mogę wyciągnąć rok, miesiąc i dzień z tekstu dopasowanego do jednego z dwóch różnych wyrażeń regularnych. Bez nazw miałabym z tym większy problem, ponieważ numery grup (których trzeba było używać wcześniej) nie zgadzałyby się ze sobą (rok to grupa 1 w pierwszym wzorcu i grupa 3 w drugim).

W ogóle lubię wyrażenia regularne! 🙂 Na poprzednim blogu pojawił się kiedyś wpis o pułapkach regeksowych w Javie. Chyba przypomnę go w przyszłym tygodniu.

  • 8. Użycie mojego własnego kodu do zamiany wartości tekstowej na typ Calendar.
  • 17 i 18: Wyrażenia regularne mają umożliwić akceptację dat takich jak: 2016-04-10, 2016.04.10, 04/10/2014. Każde z wyrażeń definiuje 3 grupy nazwane: year, month oraz day.
  • 39-41: Odwołuję się do grup, które są obecne niezależnie od tego, który z dwóch wzorców zadziałał.
  • 43: Dość lekkie testy poprawności daty dopasowanej do wzorca. Zajrzałam do implementacji kalendarza. Podanie nieistniejącego dnia miesiąca nie powinno spowodować rzucenia wyjątku. Jeśli użytkownik będzie uparcie twierdził, że urodził się 30 lutego… Mało mnie interesuje, jaką datę ustawi mu system.
  • 45: Ustawiam odpowiednią datę w moim kalendarzu. Początkowo chciałam mieć w tym miejscu obiekt typu Date, ale zorientowałam się, że tworzenie instancji Date w oparciu o rok, miesiąc i dzień od dawna nie jest zalecane.

Na koniec pozdrawiam z Warszawy! Przyjechałam z całą rodziną na konferencję 4Developers.

3.. 2.. 1.. Witaj, Spring Boot!

Dopiero teraz, przy piątym wpisie w ramach konkursu Daj się poznać, osiągnęłam etap aplikacji “Witaj Świecie”. No cóż. W tym artykule opowiem krótko co przy tej okazji zrobiłam i co mnie zaskoczyło. Kod jest, oczywiście, dostępny w GitHubie.

Szkielet aplikacji

Za radą Java Magazine, szkielet aplikacji wygenerowałam przy użyciu serwisu Spring Initializr.

Struktura projektu Spring Boot
Struktura projektu Spring Boot

Najważniejsze elementy w strukturze aplikacji to (tradycyjnie zresztą):

  • katalog src/main/java z kodem w języku Java (domyślnie wypełniany przez Spring Initializr jedną klasą o nazwie Application),
  • katalog src/test/java z testami jednostkowymi,
  • src/main/resources to miejsce na zasoby; podkatalog static ma zawierać pliki przetwarzane po stronie klienta (obrazki, javascript), a podkatalog templates szablony przetwarzane po stronie serwera,
  • plik pom.xml to informacje dla Mavena, którego wybrałam jako narzędzie do budowania mojego projektu; zawiera przede wszystkim listę potrzebnych mi bibliotek.
Hello World!

Aplikacja kompilowała się już w poprzedniej odsłonie, ale teraz zależało mi na jej uruchomieniu i wyświetleniu czegoś w przeglądarce. W oparciu o tutorial na stronie Springa powstał ten oto skomplikowany kontroler:

  • @RestController to adnotacja, która sprawi, że klasa będzie mogła obsługiwać żądania REST. Jej użycie jest równoważne zastosowaniu dwóch innych adnotacji: @Controller and @ResponseBody. W ten sposób tworzę kontroler, który zwraca dane tekstowe (a nie kod HTML).
  • @RequestMapping pozwala określić adres, pod jakim ma być dostępny kontroler. W naszym wypadku będzie to adres najwyższego rzędu.

Klasa uruchamiająca aplikację wygląda w najprostszej wersji tak:

  • Adnotacja @SpringBootApplication również grupuje kilka innych adnotacji. Być może najistotniejsza z nich to @ComponentScan. Dzięki niej pakiet, w którym umieściłam kod zostanie przeszukany pod kątem usług sieciowych – w ten sposób znaleziony zostanie HelloController.

Za radą tutoriala urozmaiciłam sobie efekt w konsoli dodając kod przeglądający ziarna (beans) dostępne w tzw. kontekście aplikacji.

Jak to wygląda w przeglądarce? Zerknij na nagłówek tego wpisu.

Poniżej przedstawiam dane wypisane w konsoli. Zwróć uwagę, że aplikacja webowa jest uruchamiania w wierszu poleceń z pliku JAR, a nie z pliku WAR wgranego na serwer. Jak to możliwe? Otóż przy aktualnej konfiguracji, wynikowy plik JAR zawiera wbudowaną wersję serwera Tomcat. Wielkość szafbook-0.0.1-SNAPSHOT.jar to 33 MB…

Głupie wtopy: co zrobiłam nie tak przy pierwszym podejściu

Problem 1: Aplikacja buduje się (przy użyciu Mavena) w Eclipse i nie buduje się na zewnątrz. Rozwiązanie: Instalacja w systemie Mavena 3 i przestawienie Eclipse na tę samą instalację (wcześniej Eclipse korzystał z instalacji wbudowanej, a w systemie miałam Mavena 2).

Problem 2: java.lang.UnsupportedClassVersionError Rozwiązanie: Zmiana wartości zmiennej  JAVA_HOME  w systemie na wersję Javy używaną przez projekt w Eclipse.

Problem 3: Aplikacja działa w przeglądarce, ale w konsoli mam “java.lang.IllegalStateException: Tomcat connector in failed state“. Rozwiązanie: Usunąć zduplikowane wywołanie SpringApplication.run 🙂 Sukcesem może zakończyć się tylko jedno z nich, potem port będzie już zajęty.

Co dalej?

Jeśli chodzi o rozwijanie projektu, to najbliższe prace poświęcone będą:

  1. Ciągłej Integracji,
  2. “M” w MVC, czyli modelowi danych.

Jeśli chodzi o blogowanie, to planuję wpisy bezpośrednio związane z rozwojem kodu, a dodatkowo:

  1. git rebase, którego znaczenie wreszcie zrozumiałam,
  2. Maven.
PS. Java Beans – ciekawostka lingwistyczna

W języku programowania Java istotną rolę pełnią tzw. “ziarenka”: JavaBeans oraz Enterprise JavaBeans. Dlaczego ziarenka? Otóż “Java” to w Stanach synonim słowa “kawa” (bardzo dużo kawy uprawiano na wyspie Jawie). Stąd pomysł, żeby najmniejsze samodzielne składowe aplikacji określić mianem “ziaren kawy”.

Oficjalne logo języka Java - parujący kubek z kawą
Oficjalne logo języka Java – parujący kubek z kawą