Do naší malé aplikace jsem dostal za úkol naimplementovat správu uživatelských práv a rolí. Z logiky použitých technologií jsme došli k balíčku spring-security. Má mnoho možností, snadnou konfiguraci a hlavně používáme spring, tak se to jeví jako logická volba. Při implementaci jsem narazil na super bug, který mi sebral asi 4 hodiny života.
V pom.xml jsem nadefinoval závislost na spring-security, Eclipse chvíli chroupala, stáhla knihovny a mohl jsem začít postupovat dle návodu. Návod si můžete nalézt zde: http://static.springsource.org/spring-security/site/tutorial.html
Nejprve jsem do web.xml doplnil nezbytný kód. Nebudu ho sem kopírovat, je to zbytečné zabírání místa.
Následovalo vytvoření souboru security-app-context.xml:
<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.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http use-expressions="true">
<intercept-url pattern="/index.xhtml" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" />
<form-login />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="rod" password="koala" authorities="supervisor, teller, user" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Všechny stránky mimo index.xhtml, pokud nebude uživatel přihlášen, nebudou zobrazeny.
Pak je nutné doplnit web.xml načtením této konfigurace:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/security-app-context.xml
</param-value>
</context-param>
<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>
Spring-security se tak nahraje při startu aplikace a bude prohlížet všechny požadavky a ty filtrovat dle pravidel.
No a teď jsem chtěl předělat přihlašovací okno, aby se uživatelé hlásili přes spring-security.
Návody hovoří o tom, že stačí poslat pole j_username a j_password stránce j_spring_security_check a dál se vše vyřeší samo. V konfiguračním souboru security-app-context.xml se pak v tagu <form-login> dá nastavit, jak se má po loginu a logoutu aplikace chovat – přesměrování po úspěšném-neúspěšném přihlášení atd.
Nojo, ale ono to nefungovalo !
Zapnuj sem logování přes log4j, ale z hlášek jsem pochopil jediné, spring-security vůbec netuší, pod jakým uživatelem se hlásím. Trvalo mi docela dlouho, než jsem přišel na příčinu – RichFaces si přegenerovává názvy polí a tak, když se mé pole jmenuje j_username a je ve formuláři form, je přejmenováno na form:username. No a spring to nemá rád. Ve verzi 3.1 již je toto vyřešeno – lze definovat, jaké jsou přihlašovací pole, ale starší verze je nutné ofixovat jinak.
Řešení? Nahradil jsem RichFaces <h:inputtext> klasickým <input type=”text”>. Najednou vše funguje, jak má…