Dziś kolejna część z cyklu o Spring Security — dodawanie i konfiguracja w projekcie
Jednocześnie przepraszam bardzo za opóźnienie, wiele się ostatnio dzieje i niestety ma to wpływ na pisanie na bieżąco :( Obiecuję, że spróbuje się ogarnąć i pisać na czas w przyszłości :)
Ale przejdźmy do rzeczy — konfiguracji Spring Security w projekcie.
Lekcja
Dodawanie SpringSecurity do projektu
Zależności Maven
Aby dodać Spring Security do projektu, dodajemy w pliku pom.xml zależności do modułów org.springframework.security:spring-security-config oraz org.springframework.security:spring-security-taglibs .
Konfiguracja XML — uproszczona
W następnym kroku, do katalogu /src/main/resources dodajemy plik security-context.xml o następującej treści:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http auto-config="true">
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="kobietydokodu" password="jakieshaslo" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Uwaga! Powyższy plik zawiera statyczną listę użytkowników wraz z ich hasłami — w dalszej części zamienimy to w taki sposób, aby korzystał z utworzonej przez nas bazy danych. Niemniej łatwiej jest skonfigurować i rozwiązywać ewentualne problemy w takiej konfiguracji — z tego powodu będziemy korzystali najpierw ze statycznej listy użytkowników, którą następnie podmienimy na dynamiczną, z użyciem bazy danych.
Dodaliśmy dwa elementy — pierwszy pozwala nam na uproszczoną konfigurację (atrybut auto-config=”true”), dzięki czemu dostajemy automatycznie:
- formularz logowania
- operacje wylogowywania
- możliwość uwierzytelniania za pomocą nagłówków protokołu HTTP (nie będziemy z tego korzystać, ale może się to przydać np. jeśli tworzymy API)
Konfiguracja web.xml
W pliku tym dokonujemy 2 zmian — po pierwsze, modyfikujemy poniższy fragment:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
Wskazując teraz lokalizację naszego pliku security-context.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/security-context.xml</param-value>
</context-param>
Spowoduje to, że plik ten będzie tzw. głównym kontekstem (więcej na ten temat możesz poczytać w lekcji 9) i będzie dotyczył wszystkich innych kontekstów (w tym naszej aplikacji webowej).
Ponadto dodajemy poniższe elementy:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Powodują one, że wszystkie zapytania HTTP będą ‘weryfikowane’ za pomocą Spring Security.
W tym miejscu warto upewnić się, czy wszystko działa poprawnie — czy możemy uruchomić naszą aplikację oraz czy po wejściu na adres (adres serwera i kontekstu aplikacji)/spring_security_login, możemy się zalogować za pomocą podanych wcześniej loginu i hasła.
Korzystamy z użytkowników w bazie danych
Ten krok pozwoli nam logować się za pomocą danych użytkowników z bazy danych — a więc jak w prawdziwej, komercyjnej aplikacji :) W tym miejscu zakładamy, że samodzielnie utworzyłaś w swojej aplikacji funkcjonalność rejestracji — czyli tak naprawdę formularz oraz klasy z adnotacjami JPA pozwalające dodawać użytkowników do bazy danych (jeśli nie jesteś pewna, jak to zrobić, przypomnij sobie z lekcji 10 (o tworzeniu formularzy i odbieraniu danych) oraz 14 (o używaniu bazy danych w aplikacji Spring MVC) ). Alternatywą jest ręczne utworzenie rekordów w bazie danych, ale prawie każda aplikacja potrzebuje możliwość rejestracji się przez użytkowników, więc lepiej zrobić to od razu.
Pierwszym krokiem jest przeniesienie połączenia z bazą danych z pliku applicationContext.xml do pliku security-context.xml . Przenosimy więc cały poniższy tag z jednego pliku do drugiego (oczywiście, w Twojej aplikacji mogą być to nieco inne dane):
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/koty" />
<property name="username" value="login" />
<property name="password" value="haslo" />
</bean>
W przeciwnym wypadku Spring Security nie ‘widziało’ by połączenia z bazą danych, a jest ono potrzebne do weryfikacji loginu i hasła.
Kolejnym krokiem jest podmiana statycznej listy użytkowników na taką, która obsługuje bazy danych. W pliku security-context.xml zamieniamy więc fragment:
<authentication-manager>
<authentication-provider>
<user-service>
<user name="kobietydokodu" password="jakieshaslo" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
Na następujący:
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query=
"SELECT username, password, enabled FROM users WHERE username=?"
authorities-by-username-query=
"SELECT username, ‘ROLE_USER’ FROM users WHERE username =? " />
</authentication-provider>
</authentication-manager>
W tym fragmencie dzieją się następujące rzeczy:
- tworzymy jdbc-user-service — jest to gotowa implementacja, która pozwala obsługiwać uwierzytelnianie z użyciem bazy danych ustawiając jedynie kilka niezbędnych atrybutów
- wskazujemy połaczenie do bazy danych (atrybut data-source-ref=”dataSource” — wskazuje nam na beana o id dataSource — tego, którego w poprzednim kroku przenieśliśmy do naszego pliku security-context.xml)
- ustawiamy zapytanie SQL, które pobierze nam użytkownika, hasło oraz informacje, czy użytkownik jest aktywny dla podanego loginu (atrybut users-by-username-query) — dzięki temu Spring pobierze te dane i zweryfikuje, czy podane login i hasło są prawidłowe
- ustawiamy zapytanie SQL, które dla określonego użytkownika pobierze nam listę ról, które on posiada — ponieważ w naszej aplikacji nie będziemy korzystać z ról (powiemy o nich w osobnym wpisie jako materiał rozszerzający w przyszłości), podane zapytanie pobiera statyczny ciąg znaków ‘ROLE_USER’ dla wybranego użytkownika (jest to uproszczone podejście, które nie do końca jest poprawnym, ale na ten moment będziemy z niego korzystać w celu pokazania idei)
Oczywiście w zależności od tego, jak wygląda Twoja baza, być może będziesz musiała zmodyfikować zapytania SQL tak, aby odpowiadały Twoim nazwom tabel i pól. Powyższy przykład można bezpośrednio użyć np. z tabelą przedstawioną na poniższym diagramie:
Kod SQL do utworzenia takiej tabeli znajdziesz poniżej:
CREATE TABLE IF NOT EXISTS `users` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`username` VARCHAR(45) NOT NULL,
`password` VARCHAR(63) NOT NULL,
`enabled` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`))
ENGINE = InnoDB
Tak skonfigurowana aplikacja powinna pozwolić na logowanie się za pomocą nazwy użytkownika i hasła zapisanych w bazie danych.
PS. Oczywiście musisz jeszcze dodać rekord do bazy danych, możesz do tego użyć poniższego zapytania SQL:
INSERT INTO users (`username`, `password`, `enabled`) VALUES ('kobietydokodu', 'jakieshaslo', 1);
Podsumowanie
W tej lekcji nauczyliśmy się dodawać Spring Security do naszego projektu — w kolejnej części będziemy zabezpieczać poszczególne czynności w naszej aplikacji, korzystać z informacji o zalogowanym użytkowniku i wyświetlać treści w zależności od tego, kim jest zalogowana osoba. Dodamy też własny formularz logowania zamiast domyślnego.
Jeśli uważasz powyższą lekcję za przydatną, mamy małą prośbę: polub nasz fanpage. Dzięki temu będziesz zawsze na bieżąco z nowymi treściami na blogu ( i oczywiście, z nowymi częściami kursu Javy). Dzięki!