GenericSecurityTokenFactory SPI を使用して、WS-Security ランタイム環境で
使用される X.509 トークンを作成できます。
これらのセキュリティー・トークンは WSSAPI および JAAS ログイン・モジュール
に使用できますが、使用できるのはこれらに限定されません。
このタスクについて
GenericSecurityTokenFactory SPI を使用して XML を含まない
X.509 トークンを作成するとき、トークンは X.509 ジェネレーターによってのみ
発行され、X.509 コンシューマーによってのみ消費されます。したがって、X.509 トークンは、個々のトークン固有の生成プログラムまたはコンシューマーで使用することのみを目的とした、シンプル・トークンと見なされます。X.509 トークンは、GenericSecurityTokenLoginModule からは
発行できません。
GenericSecurityTokenFactory は、X509GenerateLoginModule での発行または
X509ConsumeLoginModule による消費が可能な X.509 トークンを作成するために使用できるいくつかの SPI を提供します。
GenericSecurityTokenFactory SPI を使用して作成された X.509 トークンには、
アウトバウンド・メッセージの署名と暗号化、またはインバウンド・メッセージの
署名の復号と検証に使用できる、公開鍵または秘密鍵 (あるいはその両方) が含まれています。
このタイプのトークンは、
以下の場合に使用します。
- メッセージの署名鍵を動的に変更する必要があるとき。
例えば、X509GenerateCallbackHandler で、構成時に署名鍵のハードコーディングが
必要な場合です。ハードコーディングされたこの値をオーバーライドしなければならない場合は、
X509GenerateLoginModule 上にスタックされた JAAS ログイン・モジュールをコーディングして、このログイン・モジュールが X.509 シンプル・トークンを共有状態にするようにできます。
X509GenerateLoginModule はその後、シンプルな X.509 トークンで指定された秘密鍵を
使用して、コールバック・ハンドラーで構成された値をオーバーライドします。
- SOAP メッセージに表示されない証明書を検証するために、複数の署名を許可する必要があるとき。これらの
メッセージには、KEYID などの属性および X509IssuerSerial によって参照される証明書が含まれています。
WS-Security エンジンは、SOAP メッセージに表示されない証明書を動的に解決しません。
証明書は X509ConsumeCallbackHandler でハードコーディングする必要があり、コールバック・ハンドラー
では 1 つの証明書のみ構成できます。
コードの実装者が証明書を解決する場合は、X509ConsumeLoginModule 上に
スタックされた JAAS ログイン・モジュールにこのコードを配置し、
目的の公開証明書を含む単純 X.509 トークンを共有状態にします。
X509ConsumeLoginModule はその後、単純 X.509 トークンで指定された公開証明書を
使用して、コールバック・ハンドラーで構成された値をオーバーライドします。
X.509 トークンの作成後、トークン内の公開鍵および秘密鍵は変更できません。
このため、作成したいトークンのタイプを決定しさらに以下のいずれかの手順で指定する
コマンドに類似したコマンドを発行して使用するトークンと JAAS ログイン・モジュールを作成する必要があります。
- シンプル X.509 トークンを作成します。
作成する
シンプル X.509 トークンのタイプを決定し、以下の一連のコマンドのいずれかに
類似するコマンドを発行します。
- 公開証明書を持つシンプル 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);
- 秘密鍵およびオプションの公開鍵を持つシンプル 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
}
- X509GenerateLoginModule または X509ConsumeLoginModule の上にスタック可能な JAAS ログイン・モジュールを作成します。
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;
}
}
- JAAS ログイン構成を作成します。
注: このステップでは、トークンを生成するために X509GenerateLoginModule 上にスタックするものと仮定します。トークンを消費するために X509ConsumeLoginModule 上にスタックする場合は、その変化に合わせてステップを調整する必要があります。
- 管理コンソールで、に移動します。
- 「認証」で、に移動します。
- 「新規」をクリックし、「別名」で test.generate.x509 と入力します。
- 「JAAS ログイン・モジュール」で「新規」をクリックし、「モジュール・クラス名」で test.tokens.MyX509LoginModule と入力します。
「ログイン・モジュール・プロキシーを使用」を選択し、「OK」をクリックします。
- 「新規」をクリックし、「モジュール・クラス名」で com.ibm.ws.wssecurity.wssapi.token.impl.X509GenerateLoginModule と入力します。
「OK」をクリックします。
- パンくずリストで「JAAS - システム・ログイン」をクリックして、JAAS システム・ログイン・ページに戻ります。
- 新しい JAAS 構成を使用するように X.509 トークン生成プログラムを構成します。
注: このステップでは、トークンを生成するために X509GenerateLoginModule 上にスタックするものと仮定します。トークンを消費するために X509ConsumeLoginModule 上にスタックする場合は、その変化に合わせてステップを調整する必要があります。
- 管理コンソールで、変更するバインディング構成を開きます。
- を選択します。
- 「認証トークン」で、変更するアウトバウンド X.509 トークンを選択します。
- 「JAAS ログイン」で test.generate.x509 を選択します。
- 「OK」 をクリックしてから、「保存」をクリックします。
- アプリケーション・サーバーを再始動して JAAS 構成の変更を適用します。
- サービスをテストします。