使用堆栈化 JAAS 登录模块来生成并使用 SAML 令牌

可使用 GenericSecurityTokenFactory API 将您创建的 SAML 令牌传递至 SAMLGenerateLoginModule 或 GenericIssuedTokenGenerateLoginModule 模块。还可使用这些 API 来获取 SAMLConsumeLoginModule 或 GenericIssuedTokenConsumeLoginModule 模块使用的 SAML 令牌。

开始之前

您必须具有 JAX-WS 服务客户机和提供者应用程序的功能集,您可以将新的 JAAS 登录模块类添加到其中。

关于此任务

此任务生成 SAML 1.1 不记名令牌,但该令牌很容易修改为使用 sender-vouches 和运行时环境所支持的任何 SAML 版本。

尽管可在 SAMLGenerateLoginModule 下堆栈登录模块以检查该类创建的 SAML 令牌,但您无法修改以此方式获取的 SAML 令牌,除非该令牌未包含数字签名。如果修改包含数字签名的 SAML 令牌,那么系统将针对您的更新来调整该 SAML 令牌的 XML;但是,因为该令牌是在更新之前签署的,所以接收方上的签名验证将失败。

此任务生成 SAML 1.1 不记名令牌,但您可使用运行时环境支持的任何 SAML 版本和类型。有关使用 GenericSecurityTokenFactory API 来创建和修改 SAML 令牌的更多信息,请参阅“开发 SAML 应用程序”。有关如何将该令牌放置到客户机的请求上下文上(而不使用 JAAS 登录模块)的更多信息,请参阅 com.ibm.wsspi.wssecurity.core.Constants 中的 com.ibm.wsspi.wssecurity.token.tokenHolder 和 com.ibm.wsspi.wssecurity.token.enableCaptureTokenContext 常量。

因为生成者示例不容易修改为使用 holder-of-key,所以在此任务的末尾提供了特定于 SAML holder-of-key 的 createSamlToken() 方法的示例。

过程

  1. 创建以下生成者 JAAS 登录模块并使其对应用程序代码可用。
    package test.tokens;
    
    import java.util.ArrayList;
    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.GenericSecurityTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
    import com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory;
    import com.ibm.wsspi.wssecurity.saml.config.CredentialConfig;
    import com.ibm.wsspi.wssecurity.saml.config.ProviderConfig;
    import com.ibm.wsspi.wssecurity.saml.config.RequesterConfig;
    import com.ibm.wsspi.wssecurity.saml.data.SAMLAttribute;
    import com.ibm.wsspi.wssecurity.core.config.KeyInformationConfig;
    import com.ibm.wsspi.wssecurity.core.config.KeyStoreConfig;
    import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
    
    public class MySamlGenerator 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 {
    
        GenericSecurityTokenFactory factory = null;
        try {
          factory = GenericSecurityTokenFactory.getInstance();
        } catch (Exception e) {
          throw new LoginException(e.toString());
        }
        if (factory == null) {
          throw new LoginException("GenericSecurityTokenFactory.getInstance() returned null");
        }
        SAMLToken myToken = null;
        try {
          myToken = createSamlToken();
        } catch (Exception e) {
          throw new LoginException(e.toString());
        }
        if (myToken == null) {
          throw new LoginException("myToken is null");
        }
    
        //Put the token in a list on the shared state where it will be available to be used by
        //stacked login modules
        factory.putGeneratorTokenToSharedState(_sharedState, myToken);
    
        return true;
      }
    
      private SAMLToken createSamlToken() throws Exception {
        //SAML Bearer example 
        SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11);
        RequesterConfig reqData = samlFactory.newBearerTokenGenerateConfig();
        reqData.setAuthenticationMethod("Password"); //Authentication method for Assertion
    
        ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
    
        CredentialConfig cred = samlFactory.newCredentialConfig ();
        cred.setRequesterNameID("Alice");   // SAML NameIdentifier
    	  
        //Add some SAML attributes:	
        SAMLAttribute attribute = new SAMLAttribute
          ("email", new String[] {"joe@websphere"},null, "WebSphere", "email", "joe");
        ArrayList<SAMLAttribute> al = new ArrayList<SAMLAttribute>();
        al.add(attribute);
        attribute = new SAMLAttribute("Membership", 
          new String[] {"Super users", "My team"}, null, null, null, null  );
        al.add(attribute);
        cred.setSAMLAttributes(al);
    
        SAMLToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);
    
        return samlToken;
      }
    
      public boolean logout() throws LoginException {
        return false;
      } 
      public boolean abort() throws LoginException {
        return false;
      }
      public boolean commit() throws LoginException {
        return true;
      }
    }
  2. 创建以下使用者 JAAS 登录模块并使其对应用程序代码可用。
    package test.tokens;
    
    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 javax.xml.namespace.QName;
    import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
    import com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
    
    public class MySamlConsumer 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 {
    
        GenericSecurityTokenFactory factory = null;
        try {
          factory = GenericSecurityTokenFactory.getInstance();
        } catch (Exception e) {
          throw new LoginException(e.toString());
        }
        if (factory == null) {
          throw new LoginException("GenericSecurityTokenFactory.getInstance() returned null");
        }
        //Get the token that was consumed by the GenericIssuedConsumeLoginModule
        SecurityToken myToken = factory.getConsumerTokenFromSharedState(_sharedState, new QName(SAMLTokenFactory.WssSamlV11Token11));
        if (myToken == null) {
            throw new LoginException("myToken is null");
        }
        if (myToken instanceof SAMLToken) {
        	//Examine the SAML token with SAML APIs
        	SAMLToken samlToken = (SAMLToken)myToken;
        	String id = samlToken.getSamlID();
        	String subjectDns = samlToken.getSubjectDNS();
        	//...    	
        } else {
        	throw new LoginException("Did not receive a SAML token");
        }
        return true;
      }
      public boolean logout() throws LoginException {
        return false;
      } 
      public boolean abort() throws LoginException {
        return false;
      }
      public boolean commit() throws LoginException {
        return true;
      }
    }
  3. 创建 JAAS 登录配置。
    1. 在管理控制台中,转至安全性 > 全局安全性
    2. 在“认证”下,转至 Java 认证和授权服务 > 系统登录
    3. 创建 SAML 令牌生成者。
      1. 单击新建,然后在“别名”下输入 test.generate.saml
      2. 在“JAAS 登录模块”下面,单击新建,然后在“模块类名”下输入 test.tokens.MySamlGenerator。选择使用登录模块代理,然后单击确定
      3. 单击新建,在“模块类名”下输入 com.ibm.ws.wssecurity.wssapi.token.impl.SAMLGenerateLoginModule。单击确定
    4. 创建 SAML 令牌使用者。
      1. 在面包屑中,单击 JAAS - 系统登录以返回至 JAAS 系统登录页面。
      2. 单击新建,然后在“别名”下输入 test.consume.saml
      3. 在“JAAS 登录模块”下面,单击新建,然后在“模块类名”下输入 com.ibm.ws.wssecurity.wssapi.token.impl.SAMLConsumeLoginModule。选择使用登录模块代理,然后单击确定
      4. 单击保存
  4. 配置 SAML 令牌生成者以使用新的 JAAS 登录配置。
    1. 在管理控制台中,打开要更改的绑定配置。
    2. 选择 WS-Security > 认证和保护
    3. 在“认证令牌”下,选择要更改的 SAML 出站令牌。
    4. 在“JAAS 登录”下,选择 test.generate.saml
  5. 配置 SAML 令牌使用者以使用新的 JAAS 配置。
    1. 在管理控制台中,打开要更改的绑定配置。
    2. 选择 WS-Security > 认证和保护
    3. 在“认证令牌”下,选择要更改的 SAML 入站令牌。
    4. 在“JAAS 登录”下,选择 test.consume.saml
  6. 单击保存
  7. 重新启动应用程序服务器以应用 JAAS 配置更改。
  8. 测试服务。

示例

以下示例说明了用于创建非对称 SAML 2.0 holder-of-key 令牌的 createSamlToken() 方法。
private SAMLToken createSamlToken() throws Exception {
  SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV20Token11);

  RequesterConfig reqData = samlFactory.newAsymmetricHolderOfKeyTokenGenerateConfig();
  reqData.setAuthenticationMethod("Password");  //Authentication method for Assertion 

  ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");

  CredentialConfig cred = samlFactory.newCredentialConfig ();
  cred.setRequesterNameID("Alice");   // SAML NameIdentifier

  // (Optional) If you want to use keystore and key properties other than what 
  // is set in the SAMLIssuerConfig.properties file, reset the keystore, 
  // trust store and alias information in the ProviderConfig object.
  KeyInformationConfig kic = samlFactory.newKeyInformationConfig("private_key","keypass","CN=Private");

  KeyStoreConfig ksc = samlFactory.newKeyStoreConfig("jks","/keystores/myKeystore.ks","storepass");

  samlIssuerCfg.setKeyStoreConfig(ksc);    //keystore that holds the private key    
  samlIssuerCfg.setTrustStoreConfig(ksc);  //keystore that holds the public key

  // Set the alias for the public certificate that must exist in the trust store.
  // This alias must not require a password.
  reqData.setKeyAliasForRequester("public_cert");  

  SecurityToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);     

  // Get the private key from the key store
  WSSUtilFactory wssufactory = WSSUtilFactory.getInstance();
  java.security.KeyStore ks = wssufactory.getKeyStore("jks","/keystores/myKeystore.ks",
                                                      "storepass".toCharArray());
  java.security.Key privateKey = ks.getKey("private_key", "keypass".toCharArray());

  // Add the private key to the token so that the token can be used to sign 
  // elements in a SOAP message. ((com.ibm.ws.wssecurity.wssapi.token.impl.SecurityTokenImpl)samlToken).
  setKey(SecurityToken.SIGNING_KEY, privateKey);  ((com.ibm.ws.wssecurity.wssapi.token.impl.SecurityTokenImpl)samlToken).
  setKey(SecurityToken.DECRYPTING_KEY, privateKey);

  return samlToken;
}

指示主题类型的图标 任务主题



时间戳记图标 最近一次更新时间: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_gen_con_token_JAAS_mod
文件名:twbs_gen_con_token_JAAS_mod.html