Dynamisches X.509-Token aus einem JAAS-Anmeldemodul im Stack generieren und konsumieren

Sie können SPIs von GenericSecurityTokenFactory verwenden, um X.509-Token zur Verwendung durch die WS-Security-Laufzeitumgebung zu erstellen. Diese Sicherheitstoken können von WSSAPIs und JAAS-Anmeldemodulen verwendet werden, aber Ihre Verwendung ist nicht auf diese Komponenten beschränkt.

Informationen zu diesem Vorgang

Wenn eine SPI von GenericSecurityTokenFactory verwendet wird, um ein X.509-Token zu erstellen, das kein XML enthält, kann dieses Token nur vom X.509-Generator ausgegeben und vom X.509-Konsumenten konsumiert werden. Daher gilt ein X.509-Token als ein einfaches Token, das nur zur Verwendung durch den entsprechenden tokenspezifischen Generator oder Konsumenten vorgesehen ist. Ein X.509-Token kann nicht vom GenericSecurityTokenLoginModule ausgegeben werden.

Die GenericSecurityTokenFactory stellt mehrere SPIs bereit, die Sie verwenden können, um X.509-Token zu erstellen, die vom X509GenerateLoginModule ausgegeben oder vom X509ConsumeLoginModule konsumiert werden können. X.509-Token, die mit einer SPI von GenericSecurityTokenFactory erstellt werden, können öffentliche und/oder private Schlüssel enthalten, mit denen eine abgehende Nachricht signiert oder verschlüsselt oder die Signatur einer eingehenden Nachricht entschlüsselt oder verifiziert werden kann.

Dieser Tokentyp kann in folgenden Situationen verwendet werden:
  • Sie möchten den Signierschlüssel für eine Nachricht dynamisch ändern. Beispielsweise könnte der X509GenerateCallbackHandler fordern, dass der Signierschlüssel zum Zeitpunkt der Konfiguration fest codiert ist. Wenn Sie diesen fest codierten Wert überschreiben möchten, können Sie ein JAAS-Anmeldemodul codieren, das im Stack über einem X509GenerateLoginModule angeordnet ist, so dass das Anmeldemodul ein einfaches X.509-Token in den Status für gemeinsame Nutzung versetzt. Das X509GenerateLoginModule verwendet in diesem Fall den im einfachen X.509-Token angegebenen privaten Schlüssel anstelle des im Callback-Handler konfigurierten Schlüssels.
  • Wenn Sie mehrere Zertifikate für Signaturverifizierung zulassen möchten, die nicht in der SOAP-Nachricht erscheinen, würden diese Nachrichten Zertifikate enthalten, die von Attributen wie KEYID und X509IssuerSerial referenziert werden. Zertifikate, die nicht in der SOAP-Nachricht erscheinen, werden von der WS-Security-Engine nicht dynamisch aufgelöst. Das Zertifikat muss im X509ConsumeCallbackHandler fest codiert sein und im Callback-Handler kann nur ein Zertifikat konfiguriert werden. Wenn Sie selbst Code zum Auflösen des Zertifikats codieren möchten, können Sie diesen Code in ein JAAS-Anmeldemodul aufnehmen, das im Stack über einem X509ConsumeLoginModule angeordnet ist, und anschließend ein einfaches X.509-Token, das das gewünschte öffentliche Zertifikat enthält, in den Status für gemeinsame Nutzung versetzen. Das X509ConsumeLoginModule würde in diesem Fall das im einfachen X.509-Token angegebene öffentliches Zertifikat anstelle des im Callback-Handler konfigurierten Zertifikats verwenden.

Nachdem ein X.509-Token erstellt wurde, können der öffentliche und private Schlüssel im Token nicht mehr modifiziert werden. Daher müssen Sie den Typ des zu erstellenden Tokens festlegen und anschließend Befehle wie in den folgenden Schritten absetzen, um Ihr Token und das JAAS-Anmeldemodul zu erstellen.

Vorgehensweise

  1. Erstellen Sie ein einfaches X.509-Token.

    Legen Sie den Typ des zu erstellenden einfachen X.509-Tokens fest, und setzen Sie Befehle wie in einer der folgenden Befehlsfolgen ab.

    1. Erstellen Sie ein einfaches X.509-Token mit einem öffentlichen Zertifikat.
      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();
      
      //Code implementieren, um das öffentliche Zertifikat anzufordern
      
      X509Token x509 = factory.getSimpleX509PublicToken(publicCert);
    2. Erstellen Sie ein einfaches X.509-Token mit einem privaten und optionalen Schlüssel.
      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();
      
      //Code implementieren, um den privaten Schlüssel anzufordern,
      //optional Code implementieren, um das öffentliche Zertifikat anzufordern
      
      X509Token x509 = null;
      try  {    
       x509 = factory.getSimpleX509PrivateToken(publicCert , privateKey);
      } catch (WSSException ex) {
       	//löst eine Ausnahme aus, wenn privateKey gleich null ist
      }
  2. Erstellen Sie ein JAAS-Anmeldemodul, das im Stack über X509GenerateLoginModule oder X509ConsumeLoginModule angeordnet werden kann.
    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 {
      //Aus Gründen der Lesbarkeit ist dieses Anmeldemodul so
      //aufgebaut, dass es nicht vor allen Nullzeigerausnahmen (NPEs) schützt
    
      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());
        }
    
        //beim Generieren (Signieren/Verschlüsseln):
        factory.putGeneratorTokenToSharedState(this._sharedState, x509);
    
        //beim Konsumieren (Entschlüsseln/Signaturverifizierung):
        factory.putConsumerTokenToSharedState(this._sharedState, x509);
    
        return true;
      }
    
      public X509Token getX509Token (GenericSecurityTokenFactory factory, 
    				 				 WSSUtilFactory utilFactory) throws Exception{
        //In diesem Beispiel wird einen Beispielkeystore verwendet
        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;
    
        //Wenn Sie das ankommende Token abrufen müssen, um es zu verarbeiten und zu ermitteln,
        //welches Zertifikat angefordert werden muss, muss das OMElement für das ankommende Token
        //abgerufen werden
        Map wssContext = utilFactory.GetWSSContext(this._handler);
        org.apache.axiom.om.OMElement element = utilFactory.getProcessingElement(wssContext);
    
        //Keystore öffnen
        java.security.KeyStore keystore = utilFactory.getKeyStore(KEYSTORE_TYPE, KEYSTORE, KEYSTORE_PASS.toCharArray());
    
        //Eintrag aus dem Keystore abrufen
        KeyStore.PasswordProtection pwdProtection = null;
        if (ALIAS_PASS != null) {
          pwdProtection = new KeyStore.PasswordProtection(ALIAS_PASS.toCharArray());
        }
        KeyStore.Entry entry = keystore.getEntry(ALIAS, pwdProtection);
    
        //Öffentlichen und/oder privaten Schlüssel aus dem Eintrag abrufen
        if (entry instanceof KeyStore.PrivateKeyEntry) {
          //Der Eintrag ist ein privater Schlüssel
          KeyStore.PrivateKeyEntry pkentry = (KeyStore.PrivateKeyEntry)entry;
          cert = pkentry.getCertificate();
          privateKey = pkentry.getPrivateKey();
        } else if (entry instanceof KeyStore.TrustedCertificateEntry) {
          //Der Eintrag ist ein öffentlicher Schlüssel
          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. Erstellen Sie eine JAAS-Anmeldekonfiguration.
    Anmerkung: In diesem Schritt wird davon ausgegangen, dass Sie ein Anmeldemodul zum Generieren eines Tokens im Stack über X509GenerateLoginModule erstellen. Wenn Sie ein Anmeldemodul zum Konsumieren eines Tokens im Stack über X509ConsumeLoginModule erstellen möchten, passen Sie die Schritte für diese Variante entsprechend an.
    1. Wählen Sie in der Administrationskonsole Sicherheit > Globale Sicherheit aus.
    2. Klicken Sie unter "Authentifizierung" auf Java Authentication and Authorization Service > Systemanmeldungen.
    3. Klicken Sie auf Neu, und geben Sie unter "Alias" test.generate.x509 ein.
    4. Klicken Sie unter "JAAS-Anmeldemodule" auf Neu und geben Sie für "Name der Modulklasse" test.tokens.MyX509LoginModule ein. Wählen Sie Proxy für Anmeldemodul verwenden aus, und klicken Sie auf OK.
    5. Klicken Sie auf Neu und geben Sie für "Name der Modulklasse" com.ibm.ws.wssecurity.wssapi.token.impl.X509GenerateLoginModule ein. Klicken Sie auf OK.
    6. Klicken Sie auf JAAS - Systemanmeldungen, um zur Seite für JAAS-Systemanmeldungen zurückzukehren.
  4. Konfigurieren Sie Ihren X.509-Tokengenerator für die Verwendung der neuen JAAS-Konfiguration.
    Anmerkung: In diesem Schritt wird davon ausgegangen, dass Sie ein Anmeldemodul zum Generieren eines Tokens im Stack über X509GenerateLoginModule erstellen. Wenn Sie ein Anmeldemodul zum Konsumieren eines Tokens im Stack über X509ConsumeLoginModule erstellen möchten, passen Sie die Schritte für diese Variante entsprechend an.
    1. Öffnen Sie in der Administrationskonsole die Bindungskonfiguration, die geändert werden soll.
    2. Wählen Sie WS-Security > Authentifizierung und Zugriffsschutz aus.
    3. Wählen Sie unter "Authentifizierungstoken" das abgehende X.509-Token aus, das Sie ändern möchten.
    4. Wählen Sie unter "JAAS-Anmeldung" test.generate.x509 aus.
    5. Klicken Sie auf OK und anschließend auf Speichern.
  5. Starten Sie den Anwendungsserver erneut, um die JAAS-Konfigurationsänderungen anzuwenden.
  6. Testen Sie den Service.

Symbol, das den Typ des Artikels anzeigt. Taskartikel



Symbol für Zeitmarke Letzte Aktualisierung: 25.05.2016
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_createx509tokens
Dateiname:twbs_createx509tokens.html