Red Hat Training

A Red Hat training course is available for Red Hat JBoss Enterprise Application Platform

18.3.2.2. カスタム LoginModule の例

次の情報は、UsernamePasswordLoginModule を拡張し、JNDI ルックアップからユーザーのパスワードとロール名を取得するカスタムログインモジュールの例を作成するのに役立ちます。
このセクションの最後に、password/<username> という形式の名前 (<username> は現在のユーザー) を使用してコンテキストを検索すると、ユーザーのパスワードを返すカスタム JNDI コンテキストログインモジュールを作成します。認証されている)。同様に、roles/<username> の形式を検索すると、要求されたユーザーのロールが返されます。の例18.26「JndiUserAndPassLoginModule Custom Login Module」JndiUserAndPassLoginModule カスタムログインモジュールのソースコードです。
これは JBossUsernamePasswordLoginModule を拡張するため、JndiUserAndPassLoginModule は JNDI ストアからユーザーのパスワードとロールを取得することに注意してください。JndiUserAndPassLoginModule は、JAASLoginModule 操作と相互作用しません。

例18.26 JndiUserAndPassLoginModule Custom Login Module

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.logging.Logger;
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
 */
public class JndiUserAndPassLoginModule 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;
  private static Logger log = Logger.getLogger(JndiUserAndPassLoginModule.class);
  /**
   * Override to obtain the userPathPrefix and rolesPathPrefix options.
   */
  @Override
  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.
   */
  @Override
  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.
   */
  @Override
  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));
    }
  }
}

例18.27 セキュリティーの定義 - 新しく作成されたカスタムログインモジュールを使用した ex2 セキュリティードメイン

/subsystem=security/security-domain=security-ex2/:add
/subsystem=security/security-domain=security-ex2/authentication=classic:add
/subsystem=security/security-domain=security-ex2/authentication=classic/login-module=ex2/:add(\
flag=required,\
code=org.jboss.book.security.ex2.JndiUserAndPassLoginModule,\
module-options=[("userPathPrefix"=>"/security/store/password"),\
("rolesPathPrefix"=>"/security/store/roles")]\
)

ユーザーのサーバー側認証に JndiUserAndPassLoginModule カスタムログインモジュールを使用するかどうかは、セキュリティードメインの例のログイン設定によって決まります。EJB JAR META-INF/jboss-ejb3.xml 記述子は、セキュリティードメインを設定します。Web アプリケーションの場合、これは WEB-INF/jboss-web.xml ファイルの一部です。

例18.28 jboss-ejb3.xml の

<?xml version="1.0"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:s="urn:security" version="3.1" impl-version="2.0">
  <assembly-descriptor>
    <s:security>
      <ejb-name>*</ejb-name>
      <s:security-domain>security-ex2</s:security-domain>
    </s:security>
  </assembly-descriptor>
</jboss:ejb-jar>

例18.29 jboss-web.xml example

<?xml version="1.0"?>
<jboss-web>
    <security-domain>security-ex2</security-domain>
</jboss-web>