如何通过WSDL4J为JAX-WS+Spring SOAP服务的WSDL添加wsp:Policy
用WSDL4J添加wsp:Policy到JAX-WS SOAP服务的WSDL
嘿,我来帮你搞定用WSDL4J给你的SOAP服务添加指定安全策略的事儿,咱们一步步来拆解:
1. 先搞定命名空间声明
首先,你的setNamespaces方法需要包含所有用到的命名空间(wsp、wsu、sp、wsaw),不然WSDL4J生成的文档会报错。示例代码如下:
private void setNamespaces(Definition definition) { // 安全策略相关命名空间 definition.addNamespace("wsp", "http://schemas.xmlsoap.org/ws/2004/09/policy"); definition.addNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); definition.addNamespace("sp", "http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"); definition.addNamespace("wsaw", "http://www.w3.org/2006/05/addressing/wsdl"); // 保留你原本已有的其他命名空间(比如soap、wsdl等) // definition.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/"); // ... }
2. 实现setPolicy方法构建完整的安全策略
接下来就是核心的setPolicy方法,我们需要用WSDL4J的API逐层构建你需要的wsp:Policy结构:
private void setPolicy(Definition definition) { ElementFactory elementFactory = definition.getElementFactory(); // 1. 创建根wsp:Policy元素,设置wsu:Id属性 Policy policy = (Policy) elementFactory.createElement(Policy.QNAME); policy.setAttribute("wsu:Id", "UserNameWSTrustBinding_IWSTrust13Async_policy"); // 2. 添加wsp:ExactlyOne容器 ExactlyOne exactlyOne = (ExactlyOne) elementFactory.createElement(ExactlyOne.QNAME); policy.addExtensibilityElement(exactlyOne); // 3. 添加wsp:All容器 All all = (All) elementFactory.createElement(All.QNAME); exactlyOne.addExtensibilityElement(all); // 4. 添加sp:TransportBinding(含内部wsp:Policy) TransportBinding transportBinding = createSecurityElement(definition, TransportBinding.QNAME); addInnerPolicyToElement(definition, transportBinding); all.addExtensibilityElement(transportBinding); // 5. 添加sp:SignedEncryptedSupportingTokens(含内部wsp:Policy) SignedEncryptedSupportingTokens signedEncryptedTokens = createSecurityElement(definition, SignedEncryptedSupportingTokens.QNAME); addInnerPolicyToElement(definition, signedEncryptedTokens); all.addExtensibilityElement(signedEncryptedTokens); // 6. 添加sp:EndorsingSupportingTokens(含内部wsp:Policy) EndorsingSupportingTokens endorsingTokens = createSecurityElement(definition, EndorsingSupportingTokens.QNAME); addInnerPolicyToElement(definition, endorsingTokens); all.addExtensibilityElement(endorsingTokens); // 7. 添加sp:Wss11并填充内容 Wss11 wss11 = createSecurityElement(definition, Wss11.QNAME); populateWss11Content(definition, wss11); all.addExtensibilityElement(wss11); // 8. 添加sp:Trust13并填充内容 Trust13 trust13 = createSecurityElement(definition, Trust13.QNAME); populateTrust13Content(definition, trust13); all.addExtensibilityElement(trust13); // 9. 添加wsaw:UsingAddressing QName usingAddressingQName = new QName("http://www.w3.org/2006/05/addressing/wsdl", "UsingAddressing"); UsingAddressing usingAddressing = (UsingAddressing) elementFactory.createElement(usingAddressingQName); all.addExtensibilityElement(usingAddressing); // 10. 将Policy添加到WSDL定义中 definition.addExtensibilityElement(policy); }
辅助方法:通用安全元素创建
为了避免重复代码,我们可以写一个通用方法创建安全策略元素:
private <T extends ExtensibilityElement> T createSecurityElement(Definition definition, QName qname) { ElementFactory elementFactory = definition.getElementFactory(); return (T) elementFactory.createElement(qname); }
辅助方法:给元素添加内部wsp:Policy
比如sp:TransportBinding内部需要嵌套wsp:Policy,我们可以用这个方法填充:
private void addInnerPolicyToElement(Definition definition, ExtensibilityElement parent) { Policy innerPolicy = (Policy) definition.getElementFactory().createElement(Policy.QNAME); // 这里填充内部Policy的具体内容,比如以TransportBinding为例: TransportToken transportToken = createSecurityElement(definition, TransportToken.QNAME); HttpToken httpToken = createSecurityElement(definition, HttpToken.QNAME); transportToken.addExtensibilityElement(httpToken); innerPolicy.addExtensibilityElement(transportToken); // 可继续添加sp:AlgorithmSuite、sp:Layout等其他子元素 // ... parent.addExtensibilityElement(innerPolicy); }
辅助方法:填充sp:Wss11和sp:Trust13的内容
根据你的需求填充这两个元素的具体配置,示例如下:
private void populateWss11Content(Definition definition, Wss11 wss11) { // 添加sp:MustSupportRefKeyIdentifier等规则 MustSupportRefKeyIdentifier refKeyId = createSecurityElement(definition, MustSupportRefKeyIdentifier.QNAME); wss11.addExtensibilityElement(refKeyId); // 其他Wss11配置项... } private void populateTrust13Content(Definition definition, Trust13 trust13) { // 添加sp:RequireClientEntropy等信任规则 RequireClientEntropy clientEntropy = createSecurityElement(definition, RequireClientEntropy.QNAME); trust13.addExtensibilityElement(clientEntropy); // 其他Trust13配置项... }
3. 将Policy关联到你的Binding
最后,你需要在setBindingForWSDLDefinition方法中添加Policy引用,把策略绑定到具体的服务Binding上:
private void setBindingForWSDLDefinition(Definition definition) { Binding binding = definition.createBinding(); // 绑定的基础配置(名称、PortType关联等) binding.setQName(new QName("你的命名空间", "你的Binding名称")); binding.setPortType(definition.getPortType(new QName("你的命名空间", "你的PortType名称"))); // 添加Policy引用,指向之前创建的Policy的Id PolicyReference policyRef = (PolicyReference) definition.getElementFactory().createElement(PolicyReference.QNAME); policyRef.setURI("#UserNameWSTrustBinding_IWSTrust13Async_policy"); binding.addExtensibilityElement(policyRef); // 完成绑定的其他配置(比如SOAP绑定细节) // ... }
注意事项
- 确保你的WSDL4J版本支持这些安全策略元素,推荐使用
1.6.3及以上版本。 - 如果依赖缺失,可能需要引入WSS4J相关依赖来处理安全策略的元素构建。
内容的提问来源于stack exchange,提问作者yogsma
相关产品推荐
相关产品推荐

