12.2.2. カスタムの LoginModule の例
UsernamePasswordLoginModule
を拡張し、JNDI ルックアップからユーザーのパスワードとロール名を取得するカスタムの Login Module の例を作成するときに、次の情報が役立ちます。
password/<username>
(<username>
が認証されている現在のユーザーである場合) の形式の名前を使用してコンテキストで検索を実行する場合に、ユーザーのパスワードを返すカスタムの JNDI コンテキストログインモジュールを作成することができるように本項で説明していきます。同様に、roles/<username>
の形式の検索は、要求されたユーザーのロールを返します。
例12.16「JndiUserAndPass カスタムのログインモジュール」 は
JndiUserAndPass
カスタムのログインモジュールのソースコードを示しています。
これは JBoss
UsernamePasswordLoginModule
を拡張するため、JndiUserAndPass
が行うことは JNDI ストアからユーザーのパスワードとロールを取得することだけです。JndiUserAndPass
は JAAS LoginModule
動作には関係しません。
例12.16 JndiUserAndPass カスタムのログインモジュール
package org.jboss.book.security.ex2; import java.security.acl.Group; import java.util.Map; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginException; import org.jboss.security.SimpleGroup; import org.jboss.security.SimplePrincipal; import org.jboss.security.auth.spi.UsernamePasswordLoginModule; /** * An example custom login module that obtains passwords and roles * for a user from a JNDI lookup. * * @author Scott.Stark@jboss.org * @version $Revision: 1.4 $ */ public class JndiUserAndPass extends UsernamePasswordLoginModule { /** The JNDI name to the context that handles the password/username lookup */ private String userPathPrefix; /** The JNDI name to the context that handles the roles/ username lookup */ private String rolesPathPrefix; /** * Override to obtain the userPathPrefix and rolesPathPrefix options. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { super.initialize(subject, callbackHandler, sharedState, options); userPathPrefix = (String) options.get("userPathPrefix"); rolesPathPrefix = (String) options.get("rolesPathPrefix"); } /** * Get the roles the current user belongs to by querying the * rolesPathPrefix + '/' + super.getUsername() JNDI location. */ protected Group[] getRoleSets() throws LoginException { try { InitialContext ctx = new InitialContext(); String rolesPath = rolesPathPrefix + '/' + super.getUsername(); String[] roles = (String[]) ctx.lookup(rolesPath); Group[] groups = {new SimpleGroup("Roles")}; log.info("Getting roles for user="+super.getUsername()); for(int r = 0; r < roles.length; r ++) { SimplePrincipal role = new SimplePrincipal(roles[r]); log.info("Found role="+roles[r]); groups[0].addMember(role); } return groups; } catch(NamingException e) { log.error("Failed to obtain groups for user="+super.getUsername(), e); throw new LoginException(e.toString(true)); } } /** * Get the password of the current user by querying the * userPathPrefix + '/' + super.getUsername() JNDI location. */ protected String getUsersPassword() throws LoginException { try { InitialContext ctx = new InitialContext(); String userPath = userPathPrefix + '/' + super.getUsername(); log.info("Getting password for user="+super.getUsername()); String passwd = (String) ctx.lookup(userPath); log.info("Found password="+passwd); return passwd; } catch(NamingException e) { log.error("Failed to obtain password for user="+super.getUsername(), e); throw new LoginException(e.toString(true)); } } }
JNDI ストアの詳細は
org.jboss.book.security.ex2.service.JndiStore
MBean に記載されています。このサービスは javax.naming.Context
プロキシを返す ObjectFactory
を JNDI にバインドします。プロキシは、password
と roles
に対して検索名のプレフィックスを確認することで、検索動作を処理します。
名前が
password
で始まる場合は、ユーザーのパスワードが要求されています。名前が roles
で始まる場合は、ユーザーのロールが要求されています。サンプルの実装はユーザー名に関係なく常に theduke
のパスワードと {"TheDuke", "Echo"}
に等しいロール名の配列を返します。希望であれば他の実装で試すことも可能です。
例のコードにはカスタムのログインモジュールをテストする簡易セッション Bean が含まれています。この例を構築、デプロイ、実行するには、例のディレクトリで次のコマンドを実行します。
[examples]$ ant -Dchap=security -Dex=2 run-example ... run-example2: [echo] Waiting for 5 seconds for deploy... [java] [INFO,ExClient] Login with user name=jduke, password=theduke [java] [INFO,ExClient] Looking up EchoBean2 [java] [INFO,ExClient] Created Echo [java] [INFO,ExClient] Echo.echo('Hello') = Hello
ユーザーのサーバー側の認証に
JndiUserAndPass
カスタムのログインモジュールを使用するという選択は、例のセキュリティドメインのログイン設定により決まります。EJB JAR META-INF/jboss.xml
記述子がセキュリティドメインを設定します。
<?xml version="1.0"?> <jboss> <security-domain>security-ex2</security-domain> </jboss>
SAR
META-INF/login-config.xml
記述子はログインモジュール設定を定義します。
<application-policy name = "security-ex2"> <authentication> <login-module code="org.jboss.book.security.ex2.JndiUserAndPass" flag="required"> <module-option name="userPathPrefix">/security/store/password</module-option> <module-option name = "rolesPathPrefix">/security/store/roles</module-option> </login-module> </authentication> </application-policy>