您可以创建具有 holder-of-key 主体集确认方法的自签发 SAML 令牌,随后使用 Java™ API for XML-Based Web Services (JAX-WS) 编程模型和 Web Service 安全 API (WSS API) 将这些令牌随 Web service 请求消息一起发送。
开始之前
本任务假设您熟悉 JAX-WS 编程模型、WSS API 接口、SAML 概念以及策略集的使用以配置和管理 Web service 设置。
请在开始本任务前,完成下列操作:
- 阅读关于使用 WSS API 发送自签发 SAML 不记名令牌的信息。
- 阅读关于通过将 WSS API 用于消息级别保护来发送自签发 SAML sender-vouches 令牌的信息。
关于此任务
此任务关注使用 SAML 安全性令牌标识的非对称密钥来生成所选 SOAP 消息元素的数字签名,以满足 holder-of-key 主体集确认方法安全性需求。发送者的 X.509 证书嵌入在 SAML 安全性令牌中。发送者使用其相应的专用密钥来签署请求消息元素的所选部分以及使用接收方的公用密钥来加密请求消息。接收方使用其专用密钥来签署响应消息的所选元素,并使用 SAML 安全性令牌中发送者的公用密钥来加密响应消息的所选元素。提供了附加到 Web service 提供程序的 Web service 安全策略以供您参考。
过程
- 创建包含 holder-of-key 主体集确认方法的 SAML 安全性令牌;例如:
WSSFactory factory = WSSFactory.getInstance();
// Initialize WSSGenerationContext
com.ibm.websphere.wssecurity.wssapi.WSSGenerationContext gencont = factory.newWSSGenerationContext();
// Initialize SAML issuer configuration via custom properties
HashMap<Object, Object> customProps = new HashMap<Object,Object>();
customProps.put(SamlConstants.ISSUER_URI_PROP, "example.com");
customProps.put(SamlConstants.TTL_PROP, "3600000");
customProps.put(SamlConstants.KS_PATH_PROP, "keystores/saml-provider.jceks");
customProps.put(SamlConstants.KS_TYPE_PROP, "JCEKS");
customProps.put(SamlConstants.KS_PW_PROP, "{xor}LCswLTovPiws");
customProps.put(SamlConstants.KEY_ALIAS_PROP, "samlissuer");
customProps.put(SamlConstants.KEY_NAME_PROP, "CN=SAMLIssuer, O=EXAMPLE");
customProps.put(SamlConstants.KEY_PW_PROP, "{xor}NDomLz4sLA==");
customProps.put(SamlConstants.TS_PATH_PROP, "keystores/saml-provider.jceks");
customProps.put(SamlConstants.TS_TYPE_PROP, "JCEKS");
customProps.put(SamlConstants.TS_PW_PROP, "{xor}LCswLTovPiws");
gencont.add(customProps); //Add custom properties
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put(SamlConstants.CONFIRMATION_METHOD, "holder-of-key");
map.put(SamlConstants.Token_REQUEST, "issue");
map.put(SamlConstants.TOKEN_TYPE, WSSConstants.SAML.SAML20_VALUE_TYPE);
map.put(SamlConstants.SAML_NAME_IDENTIFIER, "Alice");
map.put(SamlConstants.SIGNATURE_REQUIRED, "true");
map.put(SamlConstants.KEY_TYPE,
"http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey");
map.put(SamlConstants.SAML_APPLIES_TO, "http://localhost:9080/your_Web_service");
map.put(SamlConstants.KEY_ALIAS, "soapinitiator" );
map.put(SamlConstants.KEY_NAME, "CN=SOAPInitator, O=ACME");
map.put(SamlConstants.KEY_PASSWORD, "keypass");
map.put(SamlConstants.KEY_STORE_PATH, "keystores/initiator.jceks");
map.put(SamlConstants.KEY_STORE_PASSWORD, "storepass");
map.put(SamlConstants.KEY_STORE_TYPE, "jceks");
SAMLGenerateCallbackHandler callbackHandler = new SAMLGenerateCallbackHandler(map);
SAMLToken samlToken = (SAMLToken) factory.newSecurityToken(SAMLToken.class,
callbackHandler, "system.wss.generate.saml");
发送者的专用密钥是以 SamlConstants.KEY_ALIAS 属性指定的且用于签署请求消息的所选元素。
- 使用 WSSGenerationContext 对象来准备请求消息安全性头处理;例如:
gencon.add(samlToken); //this line of code can be omitted
WSSTimestamp timestamp = factory.newWSSTimestamp();
gencon.add(timestamp);
WSSSignature sig = factory.newWSSSignature(samlToken);
sig.setTokenReference(SecurityToken.REF_KEYID);
//If the gencon.add(samlToken); line of code is omitted,
//the above line of code must be replaced with
//sig.setTokenReference(SecurityToken.REF_STR);
sig.setSignatureMethod(WSSSignature.RSA_SHA1);
sig.setCanonicalizationMethod(WSSSignature.EXC_C14N);
sig.addSignPart(WSSSignature.BODY);
sig.addSignPart(WSSSignature.TIMESTAMP);
sig.addSignPart(WSSSignature.ADDRESSING_HEADERS);
gencon.add(sig);
X509GenerateCallbackHandler x509callbackHandler2 = new X509GenerateCallbackHandler(
null,
"keystores/initiator.jceks",
"jceks",
"storepass".toCharArray(),
"soaprecipient",
null,
"", null);
SecurityToken st2 = factory.newSecurityToken(X509Token.class, x509callbackHandler2);
WSSEncryption enc = factory.newWSSEncryption(st2);
enc.addEncryptPart(WSSEncryption.BODY_CONTENT);
enc.addEncryptPart(WSSEncryption.SIGNATURE);
enc.setEncryptionMethod(WSSEncryption.AES256);
enc.setKeyEncryptionMethod(WSSEncryption.KW_RSA_OAEP);
gencon.add(enc);
在此示例中,加密使用 256 位密钥大小,所以您必须导入 Java 密码术扩展 (JCE) 策略文件。有关更多信息,请阅读“调节 Web Service 安全应用程序”主题中关于使用未受限 JCE 策略文件的信息。
- 创建 WSSConsumingContext 对象来准备响应消息安全性头处理;例如:
WSSConsumingContext concont = factory.newWSSConsumingContext();
HashMap<Object, Object> map = new HashMap<Object, Object>();
SAMLConsumerCallbackHandler callbackHandler = new SAMLConsumerCallbackHandler(map);
WSSDecryption dec = factory.newWSSDecryption(SAMLToken.class, callbackHandler,
"system.wss.consume.saml");
dec.addAllowedEncryptionMethod(WSSDecryption.AES256);
dec.addAllowedKeyEncryptionMethod(WSSDecryption.KW_RSA_OAEP);
dec.encryptKey(false);
dec.addRequiredDecryptPart(WSSDecryption.BODY_CONTENT);
concont.add(dec);
X509ConsumeCallbackHandler verHandler = new X509ConsumeCallbackHandler(null,
"keystores/initiator.jceks",
"jceks",
"storepass".toCharArray(),
"soaprecipient",
null, null);
WSSVerification ver = factory.newWSSVerification(X509Token.class, verHandler);
ver.addRequiredVerifyPart(WSSVerification.BODY);
concont.add(ver);
- 使用 JDK keytool 实用程序来生成 saml-provider.jceks、initiator.jceks 和 recipient.jceks 文件,这些文件用于测试示例代码;例如:
keytool -genkey -alias samlissuer -keystore saml-provider.jceks -dname "CN=SAMLIssuer, O=ACME" -storepass myissuerstorepass -keypass myissuerkeypass
-storetype jceks -validity 5000 -keyalg RSA -keysize 2048
keytool -genkey -alias soaprecipient -keystore recipient.jceks -dname "CN=SOAPRecipient, O=ACME" -storepass myreciptstorepass -keypass myreciptkeypass
-storetype jceks -validity 5000 -keyalg RSA -keysize 2048
keytool -genkey -alias soapinitiator -keystore initiator.jceks -dname "CN=SOAPInitator, O=ACME" -storepass myinitatstorepass -keypass myinitatkeypass
-storetype jceks -validity 5000 -keyalg RSA -keysize 2048
keytool -export -alias samlissuer -file issuerpub.cer -keystore saml-provider.jceks -storepass myissuerstorepass -storetype jceks
keytool -export -alias soaprecipient -file reciptpub.cer -keystore recipient.jceks -storepass myreciptstorepass -storetype jceks
keytool -export -alias soapinitiator -file initatpub.cer -keystore initiator.jceks -storepass myinitatstorepass -storetype jceks
keytool -import -alias samlissuer -file issuerpub.cer -keystore initiator.jceks -storepass myissuerstorepass -storetype jceks -keypass myissuerkeypass -noprompt
keytool -import -alias soaprecipient -file reciptpub.cer -keystore initiator.jceks -storepass myreciptstorepass -storetype jceks -keypass myreciptkeypass -noprompt
keytool -import -alias samlissuer -file issuerpub.cer -keystore recipient.jceks -storepass myreciptstorepass -storetype jceks -keypass myreciptkeypass -noprompt
keytool -import -alias soapinitiator -file initatpub.cer -keystore initiator.jceks -storepass myinitatstorepass -storetype jceks -keypass myinitatkeypass -noprompt
keytool -import -alias soapinitiator -file initatpub.cer -keystore saml-provider.jceks -storepass myissuerstorepass -storetype jceks -keypass myissuerkeypass -noprompt
结果
您已了解关键构建块来创建 Web service 客户机应用程序以在 SOAP 消息中发送 SAML 安全性令牌以及使用嵌入在消息级别保护中的 SAML 安全性内的非对称密钥。
示例
以下示例说明 Web service 提供程序 Web service 安全策略:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:spe="http://www.ibm.com/xmlns/prod/websphere/200605/ws-securitypolicy-ext">
<wsp:Policy wsu:Id="response:app_encparts">
<sp:EncryptedElements>
<sp:XPath>/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
and local-name()='Envelope']/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
and local-name()='Security']/*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#' and local-name()='Signature']</sp:XPath>
<sp:XPath>/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
and local-name()='Envelope']/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
and local-name()='Security']/*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#' and local-name()='Signature']</sp:XPath>
</sp:EncryptedElements>
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
</wsp:Policy>
<wsp:Policy wsu:Id="request:req_enc">
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
</wsp:Policy>
<wsp:Policy wsu:Id="request:app_signparts">
<sp:SignedParts>
<sp:Body/>
<sp:Header Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing"/>
</sp:SignedParts>
<sp:SignedElements>
<sp:XPath>/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
and local-name()='Envelope']/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
and local-name()='Security']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
and local-name()='Timestamp']</sp:XPath>
<sp:XPath>/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
and local-name()='Envelope']/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
and local-name()='Security']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
and local-name()='Timestamp']</sp:XPath>
</sp:SignedElements>
</wsp:Policy>
<wsp:Policy wsu:Id="response:resp_sig">
<sp:SignedParts>
<sp:Body/>
</sp:SignedParts>
</wsp:Policy>
<sp:AsymmetricBinding>
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<spe:CustomToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/Always"/>
<wsp:Policy>
<spe:WssCustomToken localname="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"/>
</wsp:Policy>
</spe:CustomToken>
</wsp:Policy>
</sp:InitiatorToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:IncludeTimestamp/>
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/Always"/>
<wsp:Policy>
<sp:WssX509V3Token11/>
</wsp:Policy>
</sp:X509Token>
<wsp:Policy>
<sp:RecipientToken>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<wsp:Policy>
<sp:AsymmetricBinding>
</wsp:Policy>