システム・ログイン構成用の JAAS カスタム・ログイン・モジュールの開発

Liberty サーバーの場合、システム・ログインを構成するための複数の Java™ 認証・承認サービス (JAAS) プラグイン・ポイントが存在します。 Liberty は、システム・ログイン構成を使用して着信要求を認証します。 カスタム JAAS ログイン・モジュールを開発して、情報をシステム・ログイン構成の Subject に追加できます。

このタスクについて

アプリケーション・ログイン構成は、特定の認証情報に基づく Subject を取得するために、サーブレット・アプリケーションによって呼び出されます。 Liberty アプリケーションのログイン構成またはシステム・ログイン構成にプラグインするログイン・モジュールを作成する場合は、特定の情報がいつ存在するか、およびその情報の使用方法を認識するログイン構成ロジックを作成する必要があります。 詳しくは、 JAAS の構成 および JAAS ログイン・モジュール を参照してください。

システム・ログイン構成の JAAS カスタム・ログイン・モジュールを開発するには、この手順のステップに従います。

手順

  • 使用可能なコールバックと、それがどのように機能するかについて理解します。

    使用可能なコールバックについて詳しくは、 JAASのプログラマチック・ログイン を参照してください。

    注: Liberty は、以下のコールバックのみをサポートします。
    callbacks[0] = new javax.security.auth.callback.NameCallback("Username: ");
    callbacks[1] = new javax.security.auth.callback.PasswordCallback("Password: ", false);
    callbacks[2] = new com.ibm.websphere.security.auth.callback.WSCredTokenCallbackImpl("Credential Token: ");
    callbacks[3] = new com.ibm.websphere.security.auth.callback.WSServletRequestCallback("HttpServletRequest: ")
    callbacks[4] = new com.ibm.websphere.security.auth.callback.WSServletResponseCallback("HttpServletResponse: ");
    callbacks[5] = new com.ibm.websphere.security.auth.callback.WSAppContextCallback("ApplicationContextCallback: ");
    callbacks[6] = new WSRealmNameCallbackImpl("Realm Name: ", default_realm);
    callbacks[7] = new WSX509CertificateChainCallback("X509Certificate[]: ");
    callbacks[8] = wsAuthMechOidCallback = new WSAuthMechOidCallbackImpl("AuthMechOid: ");
  • 共有状態変数と、それがどのように機能するかについて理解します。
    ログイン時に WebSphere® Application Server WebSphere Application Server traditional が作成するオブジェクトにアクセスする場合は、以下の共有状態変数を参照してください。 これらの変数について詳しくは、 プログラミング・インターフェースの「 システム・プログラミング・インターフェース 」サブトピックを参照してください。
    com.ibm.wsspi.security.auth.callback.Constants.WSPRINCIPAL_KEY
    java.security.Principal インターフェースの実装されたオブジェクトを指定します。 この共有状態変数は、読み取り専用です。 カスタム・ログイン・モジュールの共有状態内でこの変数を設定しないでください。 デフォルトのログイン・モジュールがこの変数を設定します。
    com.ibm.wsspi.security.auth.callback.Constants.WSCREDENTIAL_KEY
    com.ibm.websphere.security.cred.WSCredential オブジェクトを指定します。 この共有状態変数は、読み取り専用です。 カスタム・ログイン・モジュールの共有状態内でこの変数を設定しないでください。 デフォルトのログイン・モジュールがこの変数を設定します。
    com.ibm.wsspi.security.auth.callback.Constants.WSSSOTOKEN_KEY
    com.ibm.wsspi.security.token.SingleSignonToken オブジェクトを指定します。 カスタム・ログイン・モジュールの共有状態内でこの変数を設定しないでください。 デフォルトのログイン・モジュールがこの変数を設定します。
  • オプション: Liberty でのカスタム JAAS ログイン・モジュールのハッシュ・テーブルを理解します。 詳しくは、 ハッシュ・テーブル・ログイン・モジュール を参照してください。
  • コールバックおよび共有状態を使用するサンプル・カスタム・ログイン・モジュールを作成します。

    以下のサンプルを使用して、いくつかのコールバックや共有状態変数の使用方法について学習することができます。

    public class CustomCallbackLoginModule implements LoginModule {
    
      protected Map<String, ?> _sharedState;
      protected Subject _subject = null;
      protected CallbackHandler _callbackHandler;
      private final String customPrivateCredential = "CustomLoginModuleCredential";
    
      /**
       * Initialization of login module
       */
      public void initialize(Subject subject, CallbackHandler callbackHandler, 
                             Map<String, ?> sharedState, Map<String, ?> options) {
        _sharedState = sharedState;
        _subject = subject;
        _callbackHandler = callbackHandler;
      }
    
      public boolean login() throws LoginException {
        try {
          AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
            public Object run() throws Exception {
              _subject.getPrivateCredentials().add(customPrivateCredential);
              return null;
            }
    
          });
        } catch (PrivilegedActionException e) {
          throw new LoginException(e.getLocalizedMessage());
        }
    
        String username = null;
        char passwordChar[] = null;
        byte[] credToken = null;
        HttpServletRequest request = null;
        HttpServletResponse response = null;
        Map appContext = null;
        String realm = null;
        String authMechOid = null;
        java.security.cert.X509Certificate[] certChain = null;
    
        NameCallback nameCallback = null;
        PasswordCallback passwordCallback = null;
        WSCredTokenCallbackImpl wsCredTokenCallback = null;
        WSServletRequestCallback wsServletRequestCallback = null;
        WSServletResponseCallback wsServletResponseCallback = null;
        WSAppContextCallback wsAppContextCallback = null;
        WSRealmNameCallbackImpl wsRealmNameCallback = null;
        WSX509CertificateChainCallback wsX509CertificateCallback = null;
        WSAuthMechOidCallbackImpl wsAuthMechOidCallback = null;
    
        Callback[] callbacks = new Callback[9];
        callbacks[0] = nameCallback = new NameCallback("Username: ");
        callbacks[1] = passwordCallback = new PasswordCallback("Password: ", false);
        callbacks[2] = wsCredTokenCallback = new WSCredTokenCallbackImpl("Credential Token: ");
        callbacks[3] = wsServletRequestCallback = new WSServletRequestCallback("HttpServletRequest: ");
        callbacks[4] = wsServletResponseCallback = new WSServletResponseCallback("HttpServletResponse: ");
        callbacks[5] = wsAppContextCallback = new WSAppContextCallback("ApplicationContextCallback: ");
        callbacks[6] = wsRealmNameCallback = new WSRealmNameCallbackImpl("Realm name:");
        callbacks[7] = wsX509CertificateCallback = new WSX509CertificateChainCallback("X509Certificate[]: ");
        callbacks[8] = wsAuthMechOidCallback = new WSAuthMechOidCallbackImpl("AuthMechOid: ");
    
        try {
          _callbackHandler.handle(callbacks);
        } catch (Exception e) {
          // handle exception
        }
    
        if (nameCallback != null)
          username = nameCallback.getName();
    
        if (passwordCallback != null)
          passwordChar = passwordCallback.getPassword();
    
        if (wsCredTokenCallback != null)
          credToken = wsCredTokenCallback.getCredToken();
    
        if (wsServletRequestCallback != null)
          request = wsServletRequestCallback.getHttpServletRequest();
    
        if (wsServletResponseCallback != null)
          response = wsServletResponseCallback.getHttpServletResponse();
    
        if (wsAppContextCallback != null)
          appContext = wsAppContextCallback.getContext();
    
        if (wsRealmNameCallback != null)
          realm = wsRealmNameCallback.getRealmName();
    
        if (wsX509CertificateCallback != null)
          certChain = wsX509CertificateCallback.getX509CertificateChain();
    
        if (wsAuthMechOidCallback != null)
          authMechOid = wsAuthMechOidCallback.getAuthMechOid();
    
        _subject.getPrivateCredentials().add("username = " + username);
        _subject.getPrivateCredentials().add("password = " + String.valueOf(passwordChar));
        _subject.getPrivateCredentials().add("realm = " + realm);
        _subject.getPrivateCredentials().add("authMechOid = " + authMechOid.toString());
    
        return true;
      }
    
      public boolean commit() throws LoginException {
        return true;
      }
    
      public boolean abort() {
        return true;
      }
    
      public boolean logout() {
        return true;
      }
    
    }
  • オプション: ハッシュ・テーブル・ログインを使用してサンプル・カスタム・ログイン・モジュールを開発します。

    以下のサンプルを使用して、ハッシュ・テーブル・ログインの使用方法を学習することができます。

    package com.ibm.websphere.security.sample;
    
    import java.util.Map;
    
    import javax.security.auth.Subject;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.login.LoginException;
    import javax.security.auth.spi.LoginModule;
    
    import com.ibm.wsspi.security.token.AttributeNameConstants;
    
    /**
     * Custom login module that adds another PublicCredential to the subject
     */
    @SuppressWarnings("unchecked")
    public class CustomHashtableLoginModule implements LoginModule {
    
      protected Map<String, ?> _sharedState;
      protected Map<String, ?> _options;
    
    /**
     * Initialization of login module
     */
      public void initialize(
        Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
          _sharedState = sharedState;
          _options = options;
      }
    
      public boolean login() throws LoginException {
        try {
          java.util.Hashtable<String, Object> customProperties = (java.util.Hashtable<String, Object>) 
            _sharedState.get(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY);
          if (customProperties == null) {
            customProperties = new java.util.Hashtable<String, Object>();
          }
    
          customProperties.put(AttributeNameConstants.WSCREDENTIAL_USERID, "userId");
          // Sample of creating custom cache key
          customProperties.put(AttributeNameConstants.WSCREDENTIAL_CACHE_KEY, "customCacheKey");
    
          /*
           * Sample for creating user ID and security name
           * customProperties.put(AttributeNameConstants.WSCREDENTIAL_UNIQUEID, "userId");
           * customProperties.put(AttributeNameConstants.WSCREDENTIAL_SECURITYNAME, "securityName");
           * customProperties.put(AttributeNameConstants.WSCREDENTIAL_REALM, "realm");
           * customProperties.put(AttributeNameConstants.WSCREDENTIAL_GROUPS, "groupList");
           */
          /*
           * Sample for creating user ID and password
           * customProperties.put(AttributeNameConstants.WSCREDENTIAL_USERID, "userId");
           * customProperties.put(AttributeNameConstants.WSCREDENTIAL_PASSWORD, "password");
           */
          Map<String, java.util.Hashtable> mySharedState = (Map<String, java.util.Hashtable>) _sharedState;
          mySharedState.put(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY, customProperties);
        } catch (Exception e) {
            throw new LoginException("LoginException: " + e.getMessage());
        }
    
        return true;
      }
    
      public boolean commit() throws LoginException {
        return true;
      }
    
      public boolean abort() {
        return true;
      }
    
      public boolean logout() {
        return true;
      }
    }

次の作業

server.xml ファイルの WEB_INBOUND および DEFAULT Java 認証・承認サービス (JAAS) システム・ログイン構成に、カスタム・ログイン・モジュールを追加します。 カスタム・ログイン・モジュール・クラスを JAR ファイル (例えば、 customLoginModule.jar) に入れ、その JAR ファイルを Liberty サーバーで使用できるようにします。 Liberty 用の JAAS カスタム・ログイン・モジュールの構成を参照してください。