所有
我正在与需要签名和政策的网络服务进行互动。
我使用绑定提供程序属性,回调处理程序,密钥库等设置我的CXF(3.1.6 wildfly捆绑)。
bp.getRequestContext().put(SecurityConstants.CALLBACK_HANDLER, new PasswordCallbackHandler());
bp.getRequestContext().put(SecurityConstants.SIGNATURE_PROPERTIES, MyUtils.class.getClassLoader().getResource("crypto.properties"));
bp.getRequestContext().put(SecurityConstants.SIGNATURE_USERNAME, "client");
CXF负责提供wsdl中定义的所有必要策略。 通讯顺利,我发送请求并收到预期的回复。
但此时,CXF Policy验证程序抛出异常:
org.apache.cxf.ws.policy.PolicyException: These policy alternatives can not be satisfied:
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}SignedParts: Soap Body is not SIGNED
at org.apache.cxf.ws.policy.AssertionInfoMap.checkEffectivePolicy(AssertionInfoMap.java:179)
at org.apache.cxf.ws.policy.PolicyVerificationInInterceptor.handle(PolicyVerificationInInterceptor.java:102)
at org.apache.cxf.ws.policy.AbstractPolicyInterceptor.handleMessage(AbstractPolicyInterceptor.java:44)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
这是签署部分的合同:
<sp:SignedParts>
<sp:Body />
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo" />
<sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action" />
<sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
收到回复:
...
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="wsse S"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#_5002">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>IirHgSUh19ly5qpPiXKVfMB2tZ4=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_5003">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>8SY6Wz36TUlZtY+31Z5EpESs5JM=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_5004">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>yvxtMZ3SC++ZOv0RPS/Ge9ETGHA=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_5005">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>t/slFuF8/W8sWGrrAuJTmtliCeU=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_5006">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>Cjcz1r8PMjV/04CLrMDpNx+e3ks=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_3">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="wsu wsse S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>6htA73nOJBrYMteWrJ9pdag3cA8=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
...
</S:Header>
<S:Body>
<ns2:getCallResponse xmlns:ns2="http://somenamespace/Schemas/" wsu:Id="_5006">
正如您所看到的,有一个对已签名部分的引用,但ID属性不在主体(如请求)级别,而是在子标记上。
我不知道这是否可能是问题,如果是服务器方面的问题,但服务是遗留的,而且无法改变它。
所以我的问题是:如何在SoapBody上禁用传入的策略验证器或特定的断言?
由于
答案 0 :(得分:1)
在Colm O hEigeartaigh帮助之后,这是实施的决议。
属性设置:
// Policy ovveride
Map<QName, SecurityPolicyValidator> validatorMap = new HashMap<>();
validatorMap.put(new QName("http://schemas.xmlsoap.org/ws/2005/07/securitypolicy", "SignedParts"), new FakeSecuredPartsValidator());
bp.getRequestContext().put(SecurityConstants.POLICY_VALIDATOR_MAP, validatorMap);
基于CXF中原始验证器的假验证器:
public class FakeSecuredPartsValidator implements SecurityPolicyValidator {
private CoverageType coverageType = CoverageType.ENCRYPTED;
/**
* Return true if this SecurityPolicyValidator implementation is capable of validating a
* policy defined by the AssertionInfo parameter
*/
@Override
public boolean canValidatePolicy(AssertionInfo assertionInfo) {
if (coverageType == CoverageType.SIGNED) {
return assertionInfo.getAssertion() != null
&& (SP12Constants.SIGNED_PARTS.equals(assertionInfo.getAssertion().getName())
|| SP11Constants.SIGNED_PARTS.equals(assertionInfo.getAssertion().getName()));
} else {
return assertionInfo.getAssertion() != null
&& (SP12Constants.ENCRYPTED_PARTS.equals(assertionInfo.getAssertion().getName())
|| SP11Constants.ENCRYPTED_PARTS.equals(assertionInfo.getAssertion().getName()));
}
}
/**
* Validate policies, set all as validates
*/
@Override
public void validatePolicies(PolicyValidatorParameters parameters, Collection<AssertionInfo> ais) {
//
// SIGNED_PARTS and ENCRYPTED_PARTS only apply to non-Transport bindings
//
if (isTransportBinding(parameters.getAssertionInfoMap(), parameters.getMessage())) {
return;
}
// Set asserted = true for all Assertions
for (AssertionInfo ai : ais) {
if (ai.isAsserted()) {
// Secured Parts could already have been asserted by one of the other validators, if
// they are a child of a SupportingToken
continue;
}
ai.setAsserted(true);
}
}
private boolean isTransportBinding(AssertionInfoMap aim, Message message) {
AssertionInfo symAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.SYMMETRIC_BINDING);
if (symAis != null) {
return false;
}
AssertionInfo asymAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.ASYMMETRIC_BINDING);
if (asymAis != null) {
return false;
}
AssertionInfo transAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.TRANSPORT_BINDING);
if (transAis != null) {
return true;
}
// No bindings, check if we are using TLS
TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class);
if (tlsInfo != null) {
// We don't need to check these policies for TLS
PolicyUtils.assertPolicy(aim, SP12Constants.ENCRYPTED_PARTS);
PolicyUtils.assertPolicy(aim, SP11Constants.ENCRYPTED_PARTS);
PolicyUtils.assertPolicy(aim, SP12Constants.SIGNED_PARTS);
PolicyUtils.assertPolicy(aim, SP11Constants.SIGNED_PARTS);
return true;
}
return false;
}
public CoverageType getCoverageType() {
return coverageType;
}
public void setCoverageType(CoverageType coverageType) {
this.coverageType = coverageType;
}
}
答案 1 :(得分:0)
服务不遵循规范,Body元素本身必须签名,而不是上面请求中的子元素。但是,最新版本的CXF允许您通过&#34; ws-security.policy.validator.map&#34;插入自定义验证逻辑。 JAX-WS属性。这是一个将QName映射到SecurityPolicyValidator实例的映射。因此,在您的情况下,您可以将SignedParts策略QName映射到默认SecuredPartsPolicyValidator的修改版本,以更改验证逻辑。