12.2. カスタムモジュール


JBossSX フレームワークとバンドルされたログインモジュールがセキュリティ環境で動作しない場合は、独自のカスタムのログインモジュール実装を書くことができます。JaasSecurityManager には Subject プリンシパルのセットの特定の使用パターンが必要です。JAAS Subject クラスの情報ストレージの機能および JaasSecurityManager と動作するログインモジュールを書くためのこうした機能の必要な使用方法を理解しておく必要があります。
本項ではこの要件を検証し、カスタムのログインモジュールを実装するときに役立つ 2 つの抽象ベースの LoginModule 実装を紹介します。
次のメソッドを使用することで Subject と関連付けられたセキュリティ情報を取得できます。
java.util.Set getPrincipals()
java.util.Set getPrincipals(java.lang.Class c)
java.util.Set getPrivateCredentials()
java.util.Set getPrivateCredentials(java.lang.Class c)
java.util.Set getPublicCredentials()
java.util.Set getPublicCredentials(java.lang.Class c)
Copy to Clipboard Toggle word wrap
Subject アイデンティティとロールに関しては、JBossSX は getPrincipals()getPrincipals(java.lang.Class) により取得されるプリンシパルのセットという最も論理的な選択をしました。使用パターンは以下のとおりです。
  • ユーザーアイデンティティ (例えばユーザー名、ソーシャルセキュリティ番号、従業員 ID) は SubjectPrincipals セットの java.security.Principal オブジェクトとして保存されます。ユーザーアイデンティティを表す Principal 実装は、プリンシパルの名前に関する比較と等値で始める必要があります。適切な実装は org.jboss.security.SimplePrincipal クラスとして使用できます。他の Principal インスタンスは必要に応じて SubjectPrincipals セットに追加できます。
  • 割り当てられたユーザーロールも Principals セットに保存され、java.security.acl.Group インスタンスを使用して名前付きロールセットでグループ化されます。Group インターフェースは Principal / Group の集まりを定義し、java.security.Principal のサブインターフェースとなります。
  • Subject に割り当てるロールセットの数はいくつでも構いません。
  • JBossSX フレームワークは RolesCallerPrincipal という名前のよく知られた 2 つのロールセットを使用します。
    • Roles グループは Subject が認証されたアプリケーションドメインで知られた名前付きロールに対する Principal の集まりです。このロールセットは EJBContext.isCallerInRole(String) のようなメソッドで使用され、EJB は現在の呼び出し側が名前付きアプリケーションドメインロールに属しているか確認するためにこれを使用できます。メソッドパーミッションの確認を実行するセキュリティインターセプタのロジックもこのロールセットを使用します。
    • CallerPrincipalGroup はアプリケーションドメインのユーザーに割り当てられた単一の Principal アイデンティティで構成されます。EJBContext.getCallerPrincipal() メソッドは CallerPrincipal を使用して、アプリケーションドメインが動作環境アイデンティティからアプリケーションに適したユーザーアイデンティティにマップすることができます。SubjectCallerPrincipalGroup がない場合は、アプリケーションアイデンティティは動作環境アイデンティティと同じです。

12.2.1. Subject の使用パターンのサポート

「カスタムモジュール」 で説明した Subject 使用パターンの正しい実装を簡略化するために、JBossSX には Subject を強制的に正しく使用するテンプレートパターンを使用して認証された Subject を生成するログインモジュールが含まれています。
AbstractServerLoginModule

2 つのうち最も汎用的なクラスは org.jboss.security.auth.spi.AbstractServerLoginModule クラスです。

これは javax.security.auth.spi.LoginModule インターフェースの実装を提供し、動作環境セキュリティインフラストラクチャに固有の主要なタスクに対し抽象メソッドが可能になります。そのクラスに関する重要な詳細は 例12.14「AbstractServerLoginModule クラスの一部」 で強調表示されています。JavaDoc コメントがサブクラスの役割を詳しく説明します。

重要

loginOk インスタンス変数は極めて重要です。ログインが成功する場合はtrue に、そうでない場合はログインメソッドを上書きするサブクラスにより false に設定されます。この変数が正しく設定されていないと、コミットメソッドはサブジェクトを正しく更新しません。
ログインフェーズの結果を追跡することで、ログインモジュールは制御フラグとのチェーン化が可能になります。これらの制御フラグは、認証処理の一環としてログインモジュールが成功する必要はありません。

例12.14 AbstractServerLoginModule クラスの一部

package org.jboss.security.auth.spi;
/**
 *  This class implements the common functionality required for a JAAS
 *  server-side LoginModule and implements the JBossSX standard
 *  Subject usage pattern of storing identities and roles. Subclass
 *  this module to create your own custom LoginModule and override the
 *  login(), getRoleSets(), and getIdentity() methods.
 */
public abstract class AbstractServerLoginModule
    implements javax.security.auth.spi.LoginModule
{
    protected Subject subject;
    protected CallbackHandler callbackHandler;
    protected Map sharedState;
    protected Map options;
    protected Logger log;

    /** Flag indicating if the shared credential should be used */
    protected boolean useFirstPass;
    /** 
     * Flag indicating if the login phase succeeded. Subclasses that
     * override the login method must set this to true on successful
     * completion of login
     */
    protected boolean loginOk;
                
    // ...
    /**
     * Initialize the login module. This stores the subject,
     * callbackHandler and sharedState and options for the login
     * session. Subclasses should override if they need to process
     * their own options. A call to super.initialize(...)  must be
     * made in the case of an override.
     *
     * <p>
     * The options are checked for the  <em>password-stacking</em> parameter.
     * If this is set to "useFirstPass", the login identity will be taken from the
     * <code>javax.security.auth.login.name</code> value of the sharedState map,
     * and the proof of identity from the
     * <code>javax.security.auth.login.password</code> value of the sharedState map.
     *
     * @param subject the Subject to update after a successful login.
     * @param callbackHandler the CallbackHandler that will be used to obtain the
     * the user identity and credentials.
     * @param sharedState a Map shared between all configured login module instances
     * @param options the parameters passed to the login module.
     */
    public void initialize(Subject subject,
                           CallbackHandler callbackHandler,
                           Map sharedState,
                           Map options)
    {
        // ...
    }
    

    /**
     *  Looks for javax.security.auth.login.name and
     *  javax.security.auth.login.password values in the sharedState
     *  map if the useFirstPass option was true and returns true if
     *  they exist. If they do not or are null this method returns
     *  false.  
     *  Note that subclasses that override the login method
     *  must set the loginOk var to true if the login succeeds in
     *  order for the commit phase to populate the Subject. This
     *  implementation sets loginOk to true if the login() method
     *  returns true, otherwise, it sets loginOk to false.
     */
    public boolean login() 
        throws LoginException
    {
        // ...
    }
    
    /**
     *  Overridden by subclasses to return the Principal that
     *  corresponds to the user primary identity.
     */
    abstract protected Principal getIdentity();
                
    /**
     *  Overridden by subclasses to return the Groups that correspond
     *  to the role sets assigned to the user. Subclasses should
     *  create at least a Group named "Roles" that contains the roles
     *  assigned to the user.  A second common group is
     *  "CallerPrincipal," which provides the application identity of
     *  the user rather than the security domain identity.
     * 
     *  @return Group[] containing the sets of roles
     */
    abstract protected Group[] getRoleSets() throws LoginException;
}
Copy to Clipboard Toggle word wrap
UsernamePasswordLoginModule

カスタムのログインモジュールに適する2つ目の抽象ベースログインモジュールは org.jboss.security.auth.spi.UsernamePasswordLoginModule です。

このログインモジュールは、文字列ベースのユーザー名をユーザーアイデンティティとして強制し、char[] パスワードを認証資格情報として強制することで、カスタムのログインモジュール実装をさらに簡略化します。また、ロールを持たないプリンシパルへの匿名ユーザー (null ユーザー名とパスワードで表示) のマッピングにも対応しています。クラスに関する重要な詳細は次のクラスの一部で強調表示されています。JavaDoc コメントがサブクラスの役割を詳しく説明しています。

例12.15 UsernamePasswordLoginModule クラスの一部

package org.jboss.security.auth.spi;

/**
 *  An abstract subclass of AbstractServerLoginModule that imposes a
 *  an identity == String username, credentials == String password
 *  view on the login process. Subclasses override the
 *  getUsersPassword() and getUsersRoles() methods to return the
 *  expected password and roles for the user.
 */
public abstract class UsernamePasswordLoginModule
    extends AbstractServerLoginModule
{
    /** The login identity */
    private Principal identity;
    /** The proof of login identity */
    private char[] credential;
    /** The principal to use when a null username and password are seen */
    private Principal unauthenticatedIdentity;

    /**
     * The message digest algorithm used to hash passwords. If null then
     * plain passwords will be used. */
    private String hashAlgorithm = null;

    /**
     *  The name of the charset/encoding to use when converting the
     * password String to a byte array. Default is the platform's
     * default encoding.
     */
     private String hashCharset = null;

    /** The string encoding format to use. Defaults to base64. */
    private String hashEncoding = null;
                
    // ...
                
    /** 
     *  Override the superclass method to look for an
     *  unauthenticatedIdentity property. This method first invokes
     *  the super version.
     *
     *  @param options,
     *  @option unauthenticatedIdentity: the name of the principal to
     *  assign and authenticate when a null username and password are
     *  seen.
     */
    public void initialize(Subject subject,
                           CallbackHandler callbackHandler,
                           Map sharedState,
                           Map options)
    {
        super.initialize(subject, callbackHandler, sharedState,
                         options);
        // Check for unauthenticatedIdentity option.
        Object option = options.get("unauthenticatedIdentity");
        String name = (String) option;
        if (name != null) {
            unauthenticatedIdentity = new SimplePrincipal(name);
        }
    }
                
    // ...
                
    /**
     *  A hook that allows subclasses to change the validation of the
     *  input password against the expected password. This version
     *  checks that neither inputPassword or expectedPassword are null
     *  and that inputPassword.equals(expectedPassword) is true;
     *
     *  @return true if the inputPassword is valid, false otherwise.
     */
    protected boolean validatePassword(String inputPassword,
                                       String expectedPassword)
    {
        if (inputPassword == null || expectedPassword == null) {
            return false;
        }
        return inputPassword.equals(expectedPassword);
    }
    
    /**
     *  Get the expected password for the current username available
     * via the getUsername() method. This is called from within the
     * login() method after the CallbackHandler has returned the
     * username and candidate password.
     *
     * @return the valid password String
     */
    abstract protected String getUsersPassword()
        throws LoginException;
}
Copy to Clipboard Toggle word wrap
ログインモジュールのサブクラス化

作成中のログインモジュールの認証技術に対して文字列ベースのユーザー名と資格情報の使用が可能であるかによって AbstractServerLoginModuleUsernamePasswordLoginModule のどちらをサブクラス化するか選択します。文字列ベースのセマンティックが有効な場合、サブクラスは UsernamePasswordLoginModule となり、有効でない場合は AbstractServerLoginModule となります。

サブクラス化の手順

カスタムのログインモジュールが実行しなければならない手順は、選択するベースのログインモジュールクラスにより異なります。セキュリティインフラストラクチャと統合するカスタムのログインモジュールを書く場合、AbstractServerLoginModule または UsernamePasswordLoginModule をサブクラス化することから始めて、ログインモジュールが認証された Principal 情報を JBossSX セキュリティマネージャーが要求する形式で提供するようにします。

AbstractServerLoginModule をサブクラス化する場合は、次を上書きする必要があります。
  • void initialize(Subject, CallbackHandler, Map, Map): 解析するカスタムのオプションがある場合。
  • boolean login(): 認証アクティビティを実行するためです。ログインに成功する場合、loginOk インスタンス変数を true に設定するようにします。ログインに失敗する場合は false となるようにします。
  • Principal getIdentity(): log() のステップで認証されるユーザーの Principal オブジェクトを返すためです。
  • Group[] getRoleSets(): login() の間に認証される Principal に割り当てられるロールが含まれる Roles という名前の Group を最低でも 1 つ返すためです。2 番目の共通の GroupCallerPrincipal という名前で、セキュリティドメインアイデンティティではなく、ユーザーのアプリケーションアイデンティティを提供します。
UsernamePasswordLoginModule をサブクラス化する場合は、次を上書きする必要があります。
  • void initialize(Subject, CallbackHandler, Map, Map): 解析するカスタムのオプションがある場合。
  • Group[] getRoleSets(): login() の間に認証される Principal に割り当てられるロールが含まれる Roles という名前の Group を最低でも 1 つ返すためです。2 番目の共通の GroupCallerPrincipal という名前で、セキュリティドメインアイデンティティではなく、ユーザーのアプリケーションアイデンティティを提供します。
  • String getUsersPassword(): getUsername() メソッドで取得できる現在のユーザー名に必要なパスワードを返すためです。getUsersPassword() メソッドは callbackhandler がユーザー名と候補パスワードを返した後に login() 内から呼び出されます。
トップに戻る
Red Hat logoGithubredditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。 最新の更新を見る.

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

Theme

© 2025 Red Hat