概要
前回、Wicketに認証機能を追加しようとしてSpring Securityを導入してみたのですが、そもそも方向性が間違っていました。Wicketには、wicket-auth-rolesという認証機能のサブプロジェクトがあります。
情報源
Wicketの公式サイトでwicket-auth-rolesの情報を探したのですが、見つかりませんでした。公式サイトからリンクされているWikiにあるかも知れませんが、現在(2010/04/13)メンテナンス中でアクセスできない状態です。
ソースは、Apachiのsvnにそれらしきリリースタグのブランチがありました。
mavenのセントラルリポジトリに見当たらないため、svnリポジトリから直接入手するしかなさそうです。
http://svn.apache.org/repos/asf/wicket/releases/wicket-1.4.7/wicket-auth-roles
また、examplesディレクトリに、wicket-auth-rolesのサンプルがあります。
http://svn.apache.org/repos/asf/wicket/releases/wicket-1.4.7/wicket-examples/src/main/java/org/apache/wicket/examples/authentication
さらに、下記サイトを参考にさせていただきました。
rio's blog
「Wicket の勉強 (4) wicket-auth-roles を使って認証/認可を実現する」
http://rio1218.blog26.fc2.com/blog-entry-82.html
サンプル
svnのexamplesを元に、既存のWicketアプリケーションに「最小限の認証機能」を分かる限り最短で導入する手順を紹介します。
1.pom.xmlにwicket-auth-rolesを追加
<dependency> <groupId>org.apache.wicket</groupId> <artifactId>wicket-auth-roles</artifactId> <version>1.4.7</version> </dependency>
2.AuthenticatedWebSessionの導入
AuthenticatedWebSessionを継承した新規クラスを追加します。
import org.apache.wicket.Request; import org.apache.wicket.authentication.AuthenticatedWebSession; import org.apache.wicket.authorization.strategies.role.Roles; public final class MyAuthenticatedWebSession extends AuthenticatedWebSession { private static final long serialVersionUID = 1L; public MyAuthenticatedWebSession(Request request) { super(request); } @Override public boolean authenticate(final String username, final String password) { return username.equals("wicket") && password.equals("wicket"); } @Override public Roles getRoles() { if (isSignedIn()) { return new Roles(Roles.ADMIN); } return null; } }
3.AuthenticatedWebApplicationの導入
Applicationクラスの継承元をWebApplicationから、AuthenticatedWebApplicationに変更
import 既存のインポートクラス・・・ import org.apache.wicket.authentication.AuthenticatedWebApplication; import org.apache.wicket.authentication.AuthenticatedWebSession; import org.apache.wicket.authentication.pages.SignInPage; public class FooApplication extends AuthenticatedWebApplication { @Override protected void init() { super.init(); 既存の実装・・・ } @Override public Class<? extends Page> getHomePage() { 既存の実装・・・ } @Override protected Class<? extends WebPage> getSignInPageClass() { return SignInPage.class; } @Override protected Class<? extends AuthenticatedWebSession> getWebSessionClass() { return MyAuthenticatedWebSession.class; } }
4.@AuthorizeInstantiationの導入
ログインしないと遷移できないページのクラスに@AuthorizeInstantiationアノテーションを追加
@AuthorizeInstantiation("ADMIN")
@AuthorizeInstantiation("ADMIN") public class AdminPage extends BasePage { ・・・
結果
上記例では、未ログインの状態でAdminPageに遷移すると、自動的にログイン画面に当たるSignInPageが開きます。
ここで、ユーザ名="wicket"、パスワード="wicket"を入力しないと先に進めません。
補足説明
- 今回はログイン画面として、組み込みのSignInPageを使用していますが、本来はこのクラスを継承した独自のPageを作成する必要があります。
- MyAuthenticatedWebSession#authenticate(String,String)では、オンコードで判定を行っていますが、実際はここでDB等からユーザ情報を取得する必要があります。
- MyAuthenticatedWebSession#getRoles()でisSignedIn()を使用してログイン判定をしていますが、スーパークラスのAuthenticatedWebApplicationでauthenticate()の戻り値をsignedInフィールドに保持しています。
public final boolean isSignedIn() { return signedIn; } public final boolean signIn(final String username, final String password) { return signedIn = authenticate(username, password); }
- 今回は、getRoles()でオンコーディングでRoles.ADMINを返していますが、ログインユーザによりロールを変える場合は、authenticate()でユーザ情報をセッション内に保持し、getRoles()内でユーザ情報から判定する必要があります。