Uwierzytelnianie (ang. authentication) to po prostu "przedstawienie się", np. za pomocą pary login/hasło lub certyfikatu. Autoryzacja (ang. authorization) to wydanie zgody na skorzystanie z zasobu.
Przechowywanie haseł zazwyczaj związane jest z zakodowaniem ich z pomocą klasy użytkowej org.apache.commons.codes.digest.DigestUtils, która udostępnia metody dla różnych rodzajów funkcji haszujących - MD5, SHA.
Jednym z ważniejszych katalogów Grails w kontekście konfiguracji bezpieczeństwa jest katalog konfiguracyjny grails-app/conf z m.in. Bootstrap.groovy. Dzięki Bootstrap.groovy Grails umożliwia wypełnienie danymi bazę danych lub...kontekst aplikacji webowej (!) Dodatkowo, podział konfiguracji według środowiska uruchomieniowego - rozwojowe, produkcyjne, testowe - pozwala na uruchomienie pewnych funkcjonalności wyłącznie w danym środowisku. Wykrycie środowiska następuje przez sprawdzenie wartości grails.util.GrailsUtil.environment, np. "development", "production". Wystarczy połączyć to z switch/case.
W ramach uwierzytelniania możemy dodatkowo skorzystać z mechanizmu CAPTCHA (ang. Completely Automated Public Turing Test to Tell Computers and Humans Apart) - na serwerze tworzony jest obrazek, na którym znajduje się ciąg przypadkowych znaków, które użytkownik będzie proszony o wpisanie. W ruch idzie wtyczka Simple Captcha Plugin. Istnieje jednak bardziej zaawansowana wtyczka jcaptcha, która poza utworzeniem obrazka pozwala na dołączenie pliku wav. Wymaga więcej wysiłku podczas konfiguracji i autorzy jedynie wspominają o niej. Wywołanie wtyczki captcha to
<img src="${createLink(controller: 'captcha', action: 'index')}" />który czytamy - dołącz obrazek utworzony przez kontroler CaptchaController metodą index. Wystarczy więc zajrzeć do odpowiedniego pliku CaptchaController.groovy i przekonać się, w jaki sposób możliwe jest przesyłanie nie tylko strumienia HTML, ale również binarnego, np. zdjęcia. CaptchaController zapisuje użyty ciąg znaków w sesji, jako session.captcha. Niestety, porównanie wprowadzonego przez użytkownika ciągu z tym utworzonym przez CAPTCHA jest na naszych barkach. Coś w stylu (Listing 7-2):
def captchaText = session.captchaKolejnym krokiem jest wykorzystanie filtrów, które w Grails nie wymagają żadnych wpisów do WEB-INF/web.xml (nie zapomnieliśmy, że Grails to w końcu aplikacja webowa, więc taki plik *musi* istnieć). Wystarczy stworzyć klasę zakończoną Filters w grails-app/conf z metodą filters. O filtrach pisałem już w relacji Tworzenie interfejsu użytkownika w Grails - rozdział 5 z "Beginning Groovy and Grails". W filtrach dostępne są obiekty controllerName, request, response, session, servletContext, applicationContext oraz params.
if (params.captcha.toUpperCase() == captchaText) {
// poprawnie wprowadzony ciąg znaków
...
}
JSecurity jest najprostszym z rozwiązań wprowadzającym pojęcia rola (ang. role) oraz uprawnienie (ang. permission). Jest prawdopodobnie bardzo podobny do tego, który sami stworzylibyśmy, jednakże jego zaletą jest to, że już istnieje i nie wymaga skomplikowanej konfiguracji. JSecurity jest zewnętrznym projektem, który ma swoją wtyczkę grailsową jsecurity. Może korzystać z różnych źródeł danych do obsługi uwierzytelniania (w książce korzysta się wyłącznie z bazy danych). Instalujemy wtyczkę poleceniem grails install-plugin jsecurity, a następnie tworzymy przestrzeń bezpieczeństwa (ang. realm) oraz klasy dziedzinowe wraz z kontrolerami i stronami GSP poleceniem grails create-db-realm. Wykonanie polecenie to również założenie katalogu grails-app/realms, w którym klasy zakończone na Realm są definicją źródeł danych do uwierzytelniania i autoryzacji użytkowników, np. względem bazy danych czy LDAP.
Wtyczka grailsowa cas-client umożliwa wykorzystanie JA-SIG Central Authentication Service (CAS). Jest to nic innego jak klient grailsowy oparty na kliencie javowym dostarczanym w CAS. Wdrożenie CASa pozwala na centralne zarządzanie użytkownikami i ich uwierzytelnianie nie tylko w aplikacjach javowych. Instalacja wtyczki to grails install-plugin cas-client. Konfigurację danych serwera CAS znajdziemy w grails-app/conf/Config.groovy. Podczas budowania aplikacji grailsowej konfiguracja CAS trafia do WEB-INF/web.xml docelowej aplikacji webowej. Parametry grailsowe rozpoczynające się na cas.* zamieniane są na odpowiednie parametry edu.yale.its.tp.cas.client.filter.*, poza cas.urlPattern oraz cas.disabled, które są specyficzne dla wtyczki grailsowej. Kontrolery zabezpieczamy filtrami lub rozszerzając własną klasę z odpowiednimi wywołaniami, np. sprawdzając, czy użytkownik ma prawo do wykonania danej operacji. Nazwa użytkownika dostępna jest w atrybucie sesyjnym CASFilter.CAS_FILTER_USER.
Jako ostatnie rozwiązanie prezentowany jest Spring Security (dawniej Acegi Security) w postaci wtyczki grailsowej acegi. Mamy do dyspozycji uwierzytelnianie z LDAP, CAS, JAAS oraz CAPTCHA. Jako to ujęli autorzy: "Grails is in many ways a glorified Spring application", więc skoro Grails to Spring Framework, więc w kontekście bezpieczeństwa nie możemy postawić na nic innego niż właśnie na Spring Security. Instalacja typowa - grails install-plugin acegi. Następnie wykonujemy grails create-auth-domains, która tworzy klasy dziedzinowe Person, Authority oraz Requestmap. Możemy utworzyć dodatkowe kontrolery i widoki poleceniem grails generate-manager, ale nie jest to konieczne, jeśli samodzielnie zamierzamy zarządzać modelem. Requestmap to zbiór informacji o zabezpieczonych stronach i jakie uprawnienia są wymagane. Dane testowe możemy utworzyć przez odpowiednie konstrukcje GORMowe na klasach dziedzinowych w Bootstrap.groovy. Konfiguracja wtyczki jest w grails-app/config/AcegiConfig.groovy. Zabezpieczanie stron możliwe jest z użyciem dedykowanych znaczników GSP, m.in. g:isLoggedIn oraz g:isNotLoggedIn. Po uwierzytelnieniu wtyczka acegi umieszcza obiekt użytkownika w sesji, więc możemy odczytać jego dane na stronie GSP, np. (Listing 7-12):
<g:isLoggedIn>Kolejny rozdział to technologie Web 2.0 w Grails. Przed nami ponownie cała masa wtyczek, więc przy okazji poznawania Grails można poznać wiele projektów wokół (pewnie nie będę oryginalny, jeśli powiem, że o wielu nie słyszałem wcześniej).
<b>${session.user?.firstName} ${session.user?.lastName}</b>
</g:isLoggedIn>
Acegi chyba jednak nie umieszcza użytkownika w sesji, tak jak sugerujesz, przytoczony kod (Listning 7-12) nic nie wyświetla.
OdpowiedzUsuńAby wyświetlić informacje o użytkowniku należałoby raczej użyć znacznika <g:loggedInUserInfo />:
<g:loggedInUserInfo field="firstName"/> <g:loggedInUserInfo field="lastName"/>
Informacje są wyświetlane tylko, jeśli użytkownik jest zalogowany, tak więc użycie <g:isLoggedIn /> staje się zbędne (w tym przypadku)
http://www.grails.org/AcegiSecurity+Plugin+-+Artifacts
Racja! Dzięki Marek za poprawkę. Siedzę z Spring Security przy innej technologi, więc (całkiem przypadkiem) znacznie łatwiej mi teraz zrozumieć temat i Twoją uwagę. Niedługo wrócę do wtyczki acegi w Grails. Jeszcze trochę... ;-)
OdpowiedzUsuń