使用 WSS API 从外部 STS 请求 SAML sender-vouches 令牌并进行消息级保护
您可以从外部安全性令牌服务 (STS) 请求具有 sender-vouches 主体集确认方法的 SAML 令牌。在获取 SAML sender-vouches 令牌之后,您随后可以使用 Java™ API for XML-Based Web Services (JAX-WS) 编程模型和 Web Service 安全 API (WSS API) 与消息级别保护将这些令牌随 Web service 请求消息一起发送。
开始之前
本任务假设您熟悉 JAX-WS 编程模型、WSS API 接口、SAML 概念、SSL 传输保护、X.509 安全性令牌以及策略集的使用以配置和管理 Web service 设置。
关于此任务
您可以从外部 STS 请求具有 sender-vouches 主体集确认方法的 SAML 令牌,然后使用 WSS API 与消息级别保护从 Web service 客户机发送 Web service 请求消息中的 SAML 令牌。
此产品没有提供缺省策略集,该策略集需要具有 sender-vouches 主体集确认方法的 SAML 令牌。阅读关于配置 SAML sender-vouches 令牌的客户机和提供程序绑定的信息,以了解关于如何创建 Web Service 安全策略来要求具有 sender-vouches 主体集确认的 SAML 令牌以及如何创建定制绑定配置的更多信息。您必须将策略和绑定附加到 Web service 提供程序。此任务中描述的代码样本假设 Web service 提供程序策略要求使用 X.509 安全性令牌以数字方式签署 SAML 令牌和消息主体。
在此任务中使用的 Web service 客户机应用程序是可供下载的 JaxWSServicesSamples 样本应用程序中包含的客户机代码的已修改版本。在过程中描述了来自样本的代码示例,且提供完整的准备使用的 Web service 客户机样本。
过程
结果
您从外部 STS 请求具有 sender-vouches 确认方法的 SAML 令牌。获取令牌之后,您使用 JAX-WS 编程模型和 WSS API 以消息级别保护将令牌随 Web service 请求消息一起发送。
示例
以下代码示例是一个准备好使用的完整 Web service 客户机应用程序,其演示如何从外部 STS 请求 SAML 令牌以及在 Web service 请求消息中以消息级别保护发送该 SAML 令牌。该样本代码说明先前描述的过程步骤。
/**
* The following source code is sample code created by IBM Corporation.
* This sample code is provided to you solely for the purpose of assisting you in the
* use of the technology. The code is provided 'AS IS', without warranty or condition of
* any kind. IBM shall not be liable for any damages arising out of your use of the
* sample code, even if IBM has been advised of the possibility of such damages.
*/
package com.ibm.was.wssample.sei.cli;
import com.ibm.was.wssample.sei.echo.EchoService12PortProxy;
import com.ibm.was.wssample.sei.echo.EchoStringInput;
import com.ibm.websphere.wssecurity.callbackhandler.SAMLGenerateCallbackHandler;
import com.ibm.websphere.wssecurity.callbackhandler.UNTGenerateCallbackHandler;
import com.ibm.websphere.wssecurity.wssapi.token.UsernameToken;
import com.ibm.websphere.wssecurity.wssapi.WSSConsumingContext;
import com.ibm.websphere.wssecurity.wssapi.WSSFactory;
import com.ibm.websphere.wssecurity.wssapi.WSSGenerationContext;
import com.ibm.websphere.wssecurity.wssapi.WSSTimestamp;
import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
import com.ibm.websphere.wssecurity.callbackhandler.X509ConsumeCallbackHandler;
import com.ibm.websphere.wssecurity.callbackhandler.X509GenerateCallbackHandler;
import com.ibm.websphere.wssecurity.wssapi.WSSException;
import com.ibm.websphere.wssecurity.wssapi.signature.WSSSignPart;
import com.ibm.websphere.wssecurity.wssapi.signature.WSSSignature;
import com.ibm.websphere.wssecurity.wssapi.verification.WSSVerification;
import com.ibm.websphere.wssecurity.wssapi.token.X509Token;
import com.ibm.wsspi.wssecurity.core.token.config.WSSConstants;
import com.ibm.wsspi.wssecurity.saml.config.SamlConstants;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertStore;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
import javax.xml.ws.BindingProvider;
public class SampleSamlSVClient {
private String urlHost = "localhost";
private String urlPort = "9080";
private static final String CONTEXT_BASE = "/WSSampleSei/";
private static final String ECHO_CONTEXT12 = CONTEXT_BASE+"EchoService12";
private String message = "HELLO";
private String uriString = "http://" + urlHost + ":" + urlPort;
private String endpointURL = uriString + ECHO_CONTEXT12;
private String input = message;
/**
* main()
*
* see printusage() for command-line arguments
*
* @param args
*/
public static void main(String[] args) {
SampleSamlSVClient sample = new SampleSamlSVClient();
sample.CallService();
}
/**
* CallService Parms were already read. Now call the service proxy classes.
*
*/
void CallService() {
String response = "ERROR!:";
try {
System.setProperty("com.ibm.SSL.ConfigURL", "profile_root/properties/ssl.client.props");
System.setProperty("java.security.auth.login.config", "profile_root/properties/wsjaas.conf");
//Request the SAML Token from external STS
WSSFactory factory = WSSFactory.getInstance();
String STS_URI = "https://externalstsserverurl:port/TrustServerWST13/services/RequestSecurityToken";
String ENDPOINT_URL = "http://localhost:9080/WSSampleSei/EchoService";
WSSGenerationContext gencont1 = factory.newWSSGenerationContext();
WSSConsumingContext concont1 = factory.newWSSConsumingContext();
HashMap<Object, Object> cbackMap1 = new HashMap<Object, Object>();
cbackMap1.put(SamlConstants.STS_ADDRESS, STS_URI);
cbackMap1.put(SamlConstants.SAML_APPLIES_TO, ENDPOINT_URL);
cbackMap1.put(SamlConstants.TRUST_CLIENT_WSTRUST_NAMESPACE, "http://docs.oasis-open.org/ws-sx/ws-trust/200512");
cbackMap1.put(SamlConstants.TRUST_CLIENT_COLLECTION_REQUEST, "false");
cbackMap1.put(SamlConstants.TOKEN_TYPE, WSSConstants.SAML.SAML11_VALUE_TYPE);
cbackMap1.put(SamlConstants.CONFIRMATION_METHOD, "sender-vouches");
SAMLGenerateCallbackHandler cbHandler1 = new SAMLGenerateCallbackHandler(cbackMap1);
// Add UNT to trust request
UNTGenerateCallbackHandler utCallbackHandler = new UNTGenerateCallbackHandler("testuser", "testuserpwd");
SecurityToken ut = factory.newSecurityToken(UsernameToken.class, utCallbackHandler);
gencont1.add(ut);
cbHandler1.setWSSConsumingContextForTrustClient(concont1);
cbHandler1.setWSSGenerationContextForTrustClient(gencont1);
SecurityToken samlToken = factory.newSecurityToken(SAMLToken.class, cbHandler1, "system.wss.generate.saml");
System.out.println("SAMLToken id = " + samlToken.getId());
// Initialize web services client.
EchoService12PortProxy echo = new EchoService12PortProxy();
echo._getDescriptor().setEndpoint(endpointURL);
// Configure SOAPAction properties
BindingProvider bp = (BindingProvider) (echo._getDescriptor().getProxy());
Map<String, Object> requestContext = bp.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
requestContext.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
requestContext.put(BindingProvider.SOAPACTION_URI_PROPERTY, "echoOperation");
// Initialize WSSGenerationContext
WSSGenerationContext gencont = factory.newWSSGenerationContext();
gencont.add(samlToken);
// Add X.509 Tokens for message protection
X509GenerateCallbackHandler x509callbackHandler = new X509GenerateCallbackHandler(
null,
"profile_root/etc/ws-security/samples/dsig-sender.ks",
"JKS",
"client".toCharArray(),
"soaprequester",
"client".toCharArray(),
"CN=SOAPRequester, OU=TRL, O=IBM, ST=Kanagawa, C=JP", null);
SecurityToken x509 = factory.newSecurityToken(X509Token.class,
x509callbackHandler, "system.wss.generate.x509");
WSSSignature sig = factory.newWSSSignature(x509);
sig.setSignatureMethod(WSSSignature.RSA_SHA1);
WSSSignPart sigPart = factory.newWSSSignPart();
sigPart.setSignPart(samlToken);
sigPart.addTransform(WSSSignPart.TRANSFORM_STRT10);
sig.addSignPart(sigPart);
sig.addSignPart(WSSSignature.BODY);
// Add timestamp
WSSTimestamp timestamp = factory.newWSSTimestamp();
gencont.add(timestamp);
sig.addSignPart(WSSSignature.TIMESTAMP);
gencont.add(sig);
WSSConsumingContext concont = factory.newWSSConsumingContext();
// Prepare to consume timestamp in response message
concont.add(WSSConsumingContext.TIMESTAMP);
// Prepare to verify digital signature in response message
X509Certificate x509cert = null;
try {
InputStream is = new FileInputStream("profile_root/etc/ws-security/samples/intca2.cer");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
x509cert = (X509Certificate) cf.generateCertificate(is);
} catch (FileNotFoundException e1) {
throw new WSSException(e1);
} catch (CertificateException e2) {
throw new WSSException(e2);
}
Set<Object> eeCerts = new HashSet<Object>();
eeCerts.add(x509cert);
java.util.List<CertStore> certList = new java.util.ArrayList<CertStore>();
CollectionCertStoreParameters certparam = new CollectionCertStoreParameters(eeCerts);
CertStore cert = null;
try {
cert = CertStore.getInstance("Collection", certparam, "IBMCertPath");
} catch (NoSuchProviderException e1) {
throw new WSSException(e1);
} catch (InvalidAlgorithmParameterException e2) {
throw new WSSException(e2);
} catch (NoSuchAlgorithmException e3) {
throw new WSSException(e3);
}
if (certList != null) {
certList.add(cert);
}
X509ConsumeCallbackHandler callbackHandlerVer = new X509ConsumeCallbackHandler(
"profile_root/etc/ws-security/samples/dsig-receiver.ks",
"JKS",
"server".toCharArray(),
certList,
java.security.Security.getProvider("IBMCertPath"));
WSSVerification ver = factory.newWSSVerification(X509Token.class, callbackHandlerVer);
ver.addRequiredVerifyPart(WSSVerification.BODY);
concont.add(ver);
gencont.process(requestContext);
concont.process(requestContext);
// Build the input object
EchoStringInput echoParm =
new com.ibm.was.wssample.sei.echo.ObjectFactory().createEchoStringInput();
echoParm.setEchoInput(input);
System.out.println(">> CLIENT: SEI Echo to " + endpointURL);
// Call the service
response = echo.echoOperation(echoParm).getEchoResponse();
System.out.println(">> CLIENT: SEI Echo invocation complete.");
System.out.println(">> CLIENT: SEI Echo response is: " + response);
} catch (Exception e) {
System.out.println(">> CLIENT: ERROR: SEI Echo EXCEPTION.");
e.printStackTrace();
}
}
}
SAMLToken id = _6CDDF0DBF91C044D211271166233407
Retrieving document at 'file:profile_root/.../wsdl/'.
>> CLIENT: SEI Echo to http://localhost:9443/WSSampleSei/EchoService12
>> CLIENT: SEI Echo invocation complete.
>> CLIENT: SEI Echo response is: SOAP12==>>HELLO