使用堆栈化 JAAS 登录模块来替换 UsernameToken 使用者的认证方法

缺省情况下,Web Service 安全性 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. 单击新建,然后指定别名 = test.consume.unt
    5. 单击新建,然后选择模块类名 = com.ibm.ws.wssecurity.wssapi.token.impl.UNTConsumeLoginModule
    6. 单击新建,然后指定模块类名 = test.tokens.MyUntAuthenticator
    7. 选择使用登录模块代理
    8. 单击确定,然后单击保存
  3. 配置 UsernameToken 令牌使用者以使用新的 JAAS 配置。
    1. 打开要更改的绑定配置。

      在管理控制台中,选择 WS-Security > 认证和保护

    2. 在“认证令牌”下,选择要更改的 UsernameToken 入站令牌。
    3. 选择 JAAS 登录 = test.consume.unt
  4. 在对 UsernameToken 使用者配置的回调处理程序上设置必需的属性。
    1. 单击回调处理程序
    2. 添加 com.ibm.wsspi.wssecurity.token.UsernameToken.authDeferred=true 定制属性。
    3. 单击确定
  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