我尝试从使用PasswordText WSS类型的Web服务获取信息。首先,我使用soapUI测试它并成功获取数据。然后,我在Java上实现身份验证,编写了SecurityHandler:
public final class SecurityHandler implements SOAPHandler<SOAPMessageContext> {
...
@Override
public boolean handleMessage(SOAPMessageContext messageContext) {
boolean outInd = (Boolean) messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outInd) {
try {
WSSecUsernameToken builder = new WSSecUsernameToken();
builder.setPasswordType(WSConstants.PASSWORD_TEXT);
builder.setUserInfo(_username, _password);
builder.addNonce();
builder.addCreated();
Document doc = messageContext.getMessage().getSOAPPart().getEnvelope().getOwnerDocument();
WSSecHeader secHeader = new WSSecHeader();
secHeader.insertSecurityHeader(doc);
builder.build(doc, secHeader);
} catch (Exception e) {
LOGGER.error("Unable to handle SOAP message", e);
return false;
}
}
return true;
}
...
}
我用
XMLUtils.PrettyDocumentToString(doc)
检查了doc对象,发现它看起来像soupUI发送的XML-所有身份验证信息(登录,密码,随机数和创建时间)都在适当的位置,Security
标签的mustUnderstand属性为true。然后我遇到了错误:
javax.xml.ws.soap.SOAPFaultException:MustUnderstand header :[{{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd} Security]不被理解
我发现了从
Security
标记中删除mustUnderstand属性的建议,但没有帮助。你有什么想法?附言
Web服务端点位于 HTTPS 上。
WSDL的策略部分:
<wsp:Policy wsu:Id="BasicHttpBinding_RelateService_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding>
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens>
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<sp:Wss10>
<wsp:Policy/>
</sp:Wss10>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
soapUI请求:
<soapenv:Envelope xmlns:ns="http://api.example.com/RelateService/1.0"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-37"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>username</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
password
</wsse:Password>
<wsse:Nonce
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
li/0YK2wxrmrHL7Cg+etdQ==
</wsse:Nonce>
<wsu:Created>2012-02-21T08:59:10.262Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ns:RetrieveCustomerByEmail>
<ns:email>[email protected]</ns:email>
<ns:firstName/>
<ns:lastName/>
</ns:RetrieveCustomerByEmail>
</soapenv:Body>
</soapenv:Envelope>
我的请求:
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
S:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="UsernameToken-1">
<wsse:Username>username</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
password
</wsse:Password>
<wsse:Nonce
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
+jeleKO9zr0/wLjAIYcmSg==
</wsse:Nonce>
<wsu:Created>2012-02-21T09:42:03.760Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</S:Header>
<S:Body>
<ns5:RetrieveCustomerByEmail xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:ns2="http://schemas.datacontract.org/2004/07/XXX.Service"
xmlns:ns3="http://schemas.datacontract.org/2004/07/XXX.Service.Relate.Contract"
xmlns:ns4="http://schemas.datacontract.org/2004/07/XXX.Service.Dto"
xmlns:ns5="http://api.example.com/RelateService/1.0"
xmlns:ns6="http://schemas.microsoft.com/2003/10/Serialization/">
<ns5:email>[email protected]</ns5:email>
<ns5:firstName/>
<ns5:lastName/>
</ns5:RetrieveCustomerByEmail>
</S:Body>
</S:Envelope>
最佳答案
当服务不处理标题时,您可能会收到此错误。该服务需要使用带有getHeaders()的SOAPHandler来解决 header 。
对于上述故障,正确的实现方法如下
@Override
public Set<QName> getHeaders() {
QName securityHeader = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security");
HashSet<QName> headers = new HashSet<QName>();
headers.add(securityHeader);
return headers;
}
当服务实际上不是安全的,但是客户端正在尝试使用安全配置(可能使用XWSS安全配置)时,也可能会获得此消息
为此,只需从浏览器检查已发布的wsdl并确保它包含预期的安全策略(将?wsdl附加到其端点URL)即可。