通过堆栈化 JAAS 登录模块来生成并使用动态 X.509 令牌

您可以使用 GenericSecurityTokenFactory SPI 来创建 X.509 令牌以供 WS-Security 运行时环境使用。这些安全性令牌可用于(但不限于)WSSAPI 和 JAAS 登录模块。

关于此任务

使用 GenericSecurityTokenFactory SPI 创建不包含 XML 的 X.509 令牌时,该令牌只能由 X.509 生成者发出且只能由 X.509 使用者使用。因此,X.509 令牌被视为简单令牌,仅供特定于其各自令牌的生成者或使用者使用。X.509 令牌不能由 GenericSecurityTokenLoginModule 发出。

GenericSecurityTokenFactory 提供若干 SPI,您可以将其用于创建 X.509 令牌,这些令牌可以由 X509GenerateLoginModule 发出或者由 X509ConsumeLoginModule 使用。使用 GenericSecurityTokenFactory SPI 创建的 X.509 令牌包含公用和/或专用密钥,其可以用于签署或加密出站消息,或者解密或验证入站消息的签名。

您可能希望使用此类型的令牌:
  • 如果您需要以动态方式更改消息的签署密钥。 例如,X509GenerateCallbackHandler 要求在配置时间对签署密钥进行硬编码。如果需要覆盖此硬编码值,您可以将 JAAS 登录模块编码(该模块堆叠在 X509GenerateLoginModule 上),以便登录模块将简单 X.509 令牌置于共享状态。然后,X509GenerateLoginModule 使用简单 X.509 令牌中指定的专用密钥来覆盖回调处理程序中配置的密钥。
  • 如果您需要允许多个签名验证证书不显示在 SOAP 消息中。这些消息将包括 KEYID 和 X509IssuerSerial 之类的属性引用的证书。WS-Security 引擎没有以动态方式解析未显示在 SOAP 消息中的证书。证书必须在 X509ConsumeCallbackHandler 中硬编码,并且您只能在回调处理程序中配置一个证书。如果您选择自己实施解析证书的代码,那么您可以将此代码置于堆叠在 X509ConsumeLoginModule 之上的 JAAS 登录模块中,然后将包含期望的公用证书的简单 X.509 令牌置于共享状态。然后,X509ConsumeLoginModule 使用简单 X.509 令牌中指定的公用证书来覆盖回调处理程序中配置的证书。

创建 X.509 令牌后,无法修改令牌中的公用和专用密钥。因此,您必须确定要创建的令牌类型,然后发出命令(类似以下步骤中指定的命令)来创建令牌和 JAAS 登录模块。

过程

  1. 创建简单 X.509 令牌

    确定要创建的简单 X.509 令牌类型,并且发出类似于以下系列命令之一的命令。

    1. 创建具有公用证书的简单 X.509 令牌。
      import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
      import com.ibm.websphere.wssecurity.wssapi.token.X509Token;
      import java.security.cert.X509Certificate;
      ...
      
      X509Certificate publicCert = null;
      
      GenericSecurityTokenFactory factory = GenericSecurityTokenFactory.getInstance();
      
      //implement code to obtain the public certificate
      
      X509Token x509 = factory.getSimpleX509PublicToken(publicCert);
    2. 创建具有专用密钥和可选公用密钥的简单 X.509 令牌。
      import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
      import com.ibm.websphere.wssecurity.wssapi.token.X509Token;
      import java.security.Key;
      import java.security.cert.X509Certificate;
      ...
      
      Key privateKey = null;
      X509Certificate publicCert = null;
      
      GenericSecurityTokenFactory factory = GenericSecurityTokenFactory.getInstance();
      
      //implement code to obtain the private key
      //optionally implement code to obtain the public certificate
      
      X509Token x509 = null;
      try {
       x509 = factory.getSimpleX509PrivateToken(publicCert , privateKey);
      } catch (WSSException ex) {
       //throws an exception if privateKey is null
      }
  2. 创建 JAAS 登录模块,该模块可以堆叠在 X509GenerateLoginModule 或 X509ConsumeLoginModule 之上。
    package test.tokens;
    import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
    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.X509Token;
    import java.security.KeyStore;
    import java.security.cert.X509Certificate;
    
    public class MyX509LoginModule implements LoginModule {
      //For the sake of readability, this login module does not
      //protect against all NPE's
    
      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;
        WSSUtilFactory utilFactory = null;
        try {
          factory = GenericSecurityTokenFactory.getInstance();
          utilFactory = WSSUtilFactory.getInstance();
        } catch (Exception e) {
          throw new LoginException(e.toString());
        }
    
        X509Token x509 = null;
        try {
          x509 = getX509Token(factory, utilFactory);
        } catch (Exception e) {
          throw new LoginException("Exception: "+e.toString());
        }
    
        //if generating (signing/encrypting):
        factory.putGeneratorTokenToSharedState(this._sharedState, x509);
    
        //if consuming (decrypting/signature verification):
        factory.putConsumerTokenToSharedState(this._sharedState, x509);
    
        return true;
      }
    
      public X509Token getX509Token (GenericSecurityTokenFactory factory, 
    				 WSSUtilFactory utilFactory) throws Exception{
        //This sample uses a sample keystore
        final String KEYSTORE = "c:/WebSphere/AppServer/profiles/AppSrv01/etc/ws-security/samples/dsig-sender.ks";
        final String KEYSTORE_PASS = "client";
        final String ALIAS = "soaprequester";
        final String ALIAS_PASS = "client";
        final String KEYSTORE_TYPE = "jks";
    
        X509Certificate publicKey = null;
        java.security.Key privateKey = null;
        java.security.cert.Certificate cert = null;
        X509Token x509 = null;
    
        //if you need to get the inbound token so that you can do some processing 
        //to determine which certificate to obtain, get then OMElement for the inbound token
        Map wssContext = utilFactory.GetWSSContext(this._handler);
        org.apache.axiom.om.OMElement element = utilFactory.getProcessingElement(wssContext);
    
        //Open the keystore
        java.security.KeyStore keystore = utilFactory.getKeyStore(KEYSTORE_TYPE, KEYSTORE, KEYSTORE_PASS.toCharArray());
    
        //Get the entry from the keystore
        KeyStore.PasswordProtection pwdProtection = null;
        if (ALIAS_PASS != null) {
          pwdProtection = new KeyStore.PasswordProtection(ALIAS_PASS.toCharArray());
        }
        KeyStore.Entry entry = keystore.getEntry(ALIAS, pwdProtection);
    
        //Get the public and/or private key from the entry
        if (entry instanceof KeyStore.PrivateKeyEntry) {
          //entry is a private key
          KeyStore.PrivateKeyEntry pkentry = (KeyStore.PrivateKeyEntry)entry;
          cert = pkentry.getCertificate();
          privateKey = pkentry.getPrivateKey();
        } else if (entry instanceof KeyStore.TrustedCertificateEntry) {
          //entry is a public key
          KeyStore.TrustedCertificateEntry tcentry = (KeyStore.TrustedCertificateEntry)entry;
          cert = tcentry.getTrustedCertificate();           
        }
        if ((cert != null) && (cert instanceof X509Certificate)) {
          publicKey = (X509Certificate)cert;
        } else {
          throw new LoginException("Certificate is not X509Certificate");
        }
    
        x509 = factory.getSimpleX509Token(publicKey, privateKey);
    
        if (x509 == null) {
          throw new LoginException("X509Token is null");
        }
    
        return x509;
      }
    
    }
  3. 创建 JAAS 登录配置。
    注: 此步骤假定您要堆叠在 X509GenerateLoginModule 上生成令牌。如果要堆叠在 X509ConsumeLoginModule 上使用令牌,那么必须调整步骤以适应此变化。
    1. 在管理控制台中,转至安全性 > 全局安全性
    2. 在“认证”下,转至 Java 认证和授权服务 > 系统登录
    3. 单击新建,然后在“别名”下输入 test.generate.x509
    4. 在“JAAS 登录模块”下,单击新建,然后在“模块类名”下输入 test.tokens.MyX509LoginModule。选择使用登录模块代理,然后单击确定
    5. 单击新建,在“模块类名”下输入 com.ibm.ws.wssecurity.wssapi.token.impl.X509GenerateLoginModule。单击确定
    6. 在面包屑中,单击 JAAS - 系统登录以返回至 JAAS 系统登录页面。
  4. 配置 X.509 令牌生成者以使用新的 JAAS 配置。
    注: 此步骤假定您要堆叠在 X509GenerateLoginModule 上生成令牌。如果要堆叠在 X509ConsumeLoginModule 上使用令牌,那么必须调整步骤以适应此变化。
    1. 在管理控制台中,打开要更改的绑定配置。
    2. 选择 WS-Security > 认证和保护
    3. 在“认证令牌”下,选择要更改的出站 X.509 令牌。
    4. 在“JAAS 登录”下,选择 test.generate.x509
    5. 单击确定,然后单击保存
  5. 重新启动应用程序服务器以应用 JAAS 配置更改。
  6. 测试服务。

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



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