概要
Wicketで作っているアプリにSpring Securityのログイン機能を追加する方法を調査中しています。WicketがURLを自動生成するのに対し、Spring SecurityはURLのパターンでアクセス制御をするので、このアンマッチがまだうまく解決できていませんが、Spring Securityの基本的な設定自体はできたので途中経過を書いておきます。
Spring Security http://static.springsource.org/spring-security/site/index.html
リファレンス http://static.springsource.org/spring-security/site/docs/3.0.x/reference/springsecurity.html
Spring Securityの設定手順
pom.xmlに追加
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>3.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>3.0.0.RELEASE</version> </dependency>
※手元の環境ではとりあえずこの2つを追記しておけば、Spring Securityが動きました。
web.xmlの冒頭に追加
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext-security.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <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>
applicationContext-security.xmlファイルを作成して、WEB-INFに配置
<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.0.xsd"> <http auto-config='true'> <intercept-url pattern="/admin/**" access="ROLE_ADMIN" /> <intercept-url pattern="/user/**" access="ROLE_USER" /> <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> </http> <authentication-manager> <authentication-provider> <user-service> <user name="adminUser" password="abc" authorities="ROLE_USER, ROLE_ADMIN" /> <user name="normalUser" password="xyz" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
結果
・「http://サーバ名/コンテキスト名/spring_security_login」でログイン画面の表示
・「http://サーバ名/コンテキスト名/admin/以下全て」には、adminUserでログインしていないとアクセス不可(強制的にログイン画面に遷移)
・「http://サーバ名/コンテキスト名/user/以下全て」には、adminUserかnormalUserでログインしていないとアクセス不可(強制的にログイン画面に遷移)
・「http://サーバ名/コンテキスト名/上記以外」はログインなしでもアクセス可能
特に何も設定していないので、ログイン画面はSpringが用意した簡単な画面が表示されますが、設定を追加すればオリジナルのログイン画面やURLが使用できます。設定の追加でユーザ情報をDBから取得するようなことも可能です。
ここまでの設定はWicketとは関係していないSpring Securityのみの設定です。またMavenがspring-coreを自動的に落としてきたので裏では使っているかもしれませんが、SpringのDIも直接は使用していません。簡単な認証機能をWebアプリに追加するだけなら、これだけの機能でも結構よさそうです。
Wicketとの連携
まだ、調査中の段階です。WicketはURLを自動生成ですが、mountBookmarkablePageとsetEnforceMounts(true)の組み合わせで、/admin/xxxといったURLを指定すればいいかもしれません。
リファレンスを見ていると、ログイン情報はJavaの中から参照可能なので、当座の対応としてコード内でチェックするルーチンを試作してみました。getPrincipal()の辺りが複数ユーザの同時ログインに対応できていなさそうですが、続きはまた後日。
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; public class LoginCheck { private final static String ROLE_ADMIN = "ROLE_ADMIN"; private final static String ROLE_USER = "ROLE_USER"; public static boolean isAdmin() { return check(ROLE_ADMIN); } public static boolean isUser() { return check(ROLE_USER); } private static boolean check(String role) { Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); boolean login = false; if (principal instanceof UserDetails) { UserDetails user = ((UserDetails) principal); for (GrantedAuthority authority : user.getAuthorities()) { if (authority.getAuthority().equals(role)) { login = true; } } } else { login = false; } return login; } }