スタックされた JAAS ログイン・モジュールを使用した UsernameToken コンシューマーの認証メソッドの置き換え

デフォルトでは、Web サービス・セキュリティーの UsernameToken コンシューマーの UNTConsumeLoginModule は、常に WebSphere レジストリーに対してトークン内に含まれているユーザー名とパスワードを検証します。GenericSecurityTokenFactory が提供する SPI を使用して、この認証方式をバイパスすることができます。

このタスクについて

UNTConsumeLoginModule が使用する認証方式を置き換える場合は、独自のカスタム JAAS ログイン・モジュールを指定して認証を行う必要があります。カスタム・ログイン・モジュールは、カスタム JAAS 構成の UNTConsumeLoginModule の下にスタックされます。 UNTConsumeLoginModule は、トークン XML を使用して検証します。ユーザー名とパスワードに指定した値の検証は、カスタムでスタックされたログイン・モジュールに据え置かれます。

UNTConsumeLoginModule を使用すると、ユーザー名とパスワードを認証するという前提があるため、動的トークンの機能を提供することのみが想定されているログイン・モジュールに対してより、この機能の実行のみが目的のスタックされたログイン・モジュールに対して、より多くの要件が設定されます。

ユーザー名とパスワードを認証しないよう UNTConsumeLoginModule に指示するには、構成されたコールバック・ハンドラーに以下のプロパティーを設定する必要があります。

com.ibm.wsspi.wssecurity.token.UsernameToken.authDeferred=true

ほとんどの WS-Security ログイン・モジュールと同様、UNTConsumeLoginModule は常に、スタック内のすべてのログイン・モジュールがアクセスできる共有状態のマップ内に、使用されるトークンを配置します。コミット・フェーズ中に authDeferred=true が指定されている場合、UNTConsumeLoginModule によって元々共有状態に置かれていた同じ UsernameToken オブジェクトが、共有状態の別のロケーションに置かれます。この UsernameToken オブジェクトが見つからない場合には、LoginException が発生します。このため、付属するログイン・モジュールがトークンを共有状態に返さずに、コールバック・ハンドラーで authDeferred=true を設定することはできません。

手順

  1. 認証を実行する JAAS ログイン・モジュールを開発し、それをアプリケーション・コードで使用できるようにします。この新しいログイン・モジュールは、com.ibm.ws.wssecurity.wssapi.token.impl.UNTConsumeLoginModule の下にスタックされます。

    このログイン・モジュールは、以下のことを行う必要があります。

    1. 次のメソッドを使用して、UNTConsumeLoginModule が消費する UsernameToken を取得します。
      UsernameToken unt = (UsernameToken)factory.getConsumerTokenFromSharedState(sharedState,UsernameToken.ValueType);
      このコード例では、ファクトリーは com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory のインスタンスです。
    2. 選択した方法でユーザー名とパスワードを確認します。

      unt.getUsername() および unt.getPassword() を呼び出して、ユーザー名とパスワードを取得することができます。

      認証エラーが発生した場合、ログイン・モジュールが LoginException をスローする必要があります。

    3. 前のサブステップで取得された UsernameToken を共有状態に戻します。

      次のメソッドを使用して、UsernameToken を共有状態に戻します。

      factory.putAuthenticatedTokenToSharedState(sharedState, unt);

    ログイン・モジュールの例を以下に示します。

    package test.tokens;
    
    import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
    import java.util.HashMap;
    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.websphere.wssecurity.wssapi.token.UsernameToken;
    
    import java.util.ArrayList;
    
    import com.ibm.wsspi.security.registry.RegistryHelper;
    import com.ibm.websphere.security.UserRegistry;
    
    public class MyUntAuthenticator implements LoginModule {
    
      private Map _sharedState;
      private Map _options;
      private CallbackHandler _handler;
    
      	public void initialize(Subject subject, CallbackHandler callbackHandler, 
                             Map<String, ?> sharedState, Map<String, ?> options) {
    
        this._handler = callbackHandler;
        this._sharedState = sharedState;
        this._options = options;  
      }
    
      public boolean login() throws LoginException {
        //For the sake of readability, this login module does not
        //protect against all NPE's
    
        GenericSecurityTokenFactory factory = null;
        WSSUtilFactory utilFactory = null;
        try {
          factory = GenericSecurityTokenFactory.getInstance();
          utilFactory = WSSUtilFactory.getInstance();
        } catch (Exception e) {
          throw new LoginException(e.toString());
        }
        if (factory == null) {
          throw new LoginException("GenericSecurityTokenFactory.getInstance() returned null");
        }
    
        UsernameToken unt = (UsernameToken)factory.getConsumerTokenFromSharedState(this._sharedState,UsernameToken.ValueType);
    
        String username = unt.getUsername();
        char [] password = unt.getPassword();
    
        //authenticate the username and password
        //to validate a PasswordDigest password 
        //String pw = yourCodeToLookUpPasswordForUsername(username);
        //boolean match = utilFactory.verifyDigestedPassword(unt, pw.toCharArray());
        //if (!match) throw new LoginException("Digested passwords do not match");
        //Example:
        try {
          simpleUserGroupCheck(username, password, "cn=group1,o=ibm,c=us");
        } catch (Exception e) {
          LoginException le = new LoginException(e.getMessage());
          le.initCause(e);
          throw le;
        }
    
        //Put the authenticated token to the shared state
        factory.putAuthenticatedTokenToSharedState(this._sharedState, unt);
    
        return true;
      }
    
      private boolean simpleUserGroupCheck(String username, char [] password, String group) throws Exception {
        String allowedGroup = null;
    
        //get the default user registry
        UserRegistry user_reg = RegistryHelper.getUserRegistry(null);
    
        //authenticate the user against the user registry
        user_reg.checkPassword(username, new String(password));
    
        //get the list of groups that the user belongs to
        java.util.List<String> groupList = user_reg.getGroupsForUser(username);
    
        //you can either use a hard-coded group
        allowedGroup = group;
    
        //or get the value from your own custom property on the callback handler
        //WSSUtilFactory util = WSSUtilFactory.getInstance();
        //Map map = util.getCallbackHandlerProperties(this._handler);
        //allowedGroup = (String) map.get("MY_ALLOWED_GROUP_1");
    
        //check if the user belongs to an allowed group
        if (!groupList.contains(allowedGroup)) {
          throw new LoginException("user ["+username+"] is not in allowed group ["+allowedGroup+"]");
        }
        return true;
    }
      //implement the rest of the methods required by the
      //LoginModule interface
    }
  2. 新規 JAAS ログイン構成を作成します。
    1. 管理コンソールで、「セキュリティー」>「グローバル・セキュリティー」とクリックします。
    2. 「認証」の下で、「Java 認証・承認サービス」を選択します。
    3. 「システム・ログイン」を選択します。
    4. 「新規」をクリックして、Alias = test.consume.unt と指定します。
    5. 「新規」をクリックし、「Module class name = com.ibm.ws.wssecurity.wssapi.token.impl.UNTConsumeLoginModule」を選択します。
    6. 「新規」をクリックして、Module class name = test.tokens.MyUntAuthenticator と指定します。
    7. 「ログイン・モジュール・プロキシーを設定」を選択します。
    8. 「OK」 をクリックして、「保存」をクリックします。
  3. 新規 JAAS 構成を使用するユーザーの UsernameToken トークン・コンシューマーを構成します。
    1. 変更するバインディング構成を開きます。

      管理コンソールで、「WS-Security」>「認証および保護」を選択します。

    2. 「認証」の下で、変更する UsernameToken インバウンド・トークンを選択します。
    3. 「JAAS login = test.consume.unt」を選択します。
  4. UsernameToken コンシューマー用に構成されたコールバック・ハンドラーに必要なプロパティーを設定します。
    1. コールバック・ハンドラー」をクリックします。
    2. com.ibm.wsspi.wssecurity.token.UsernameToken.authDeferred=true カスタム・プロパティーを追加します。
    3. 「OK」をクリックします。
  5. 「保存」をクリックします。
  6. アプリケーション・サーバーを再始動して JAAS 構成の変更を適用します。
  7. サービスをテストします。

トピックのタイプを示すアイコン タスク・トピック



タイム・スタンプ・アイコン 最終更新: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_replace_authmethod_usernametoken
ファイル名:twbs_replace_authmethod_usernametoken.html