我试图从java调用web服务.这基本上并不困难,除了webservice期望以用户名和密码以及nonce形式的某些安全性.
当我尝试从SoapUi调用web服务时,我看到原始消息如下所示:
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
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">
usr
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
>pw
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
>4smQZF5KMSktEXrQc0v5yw==
2015-02-13T12:12:41.784Z
392
false
消息中明显的元素是用户名,密码和创建,但令我困惑的是随机数.在该示例中,该字段具有值4smQZF5KMSktEXrQc0v5yw ==,但是每个请求处的该值差异(这是有意义的,因为根据维基百科,nonce是仅使用一次的任意数字).在搜索时,我找不到任何有关如何在java中生成nonce的可用示例(尽管我在堆栈溢出时发现了一些php示例,但我无法轻松验证它们的工作天气).虽然我不介意自己构建这个nonce,但我想知道这是否真的有必要,我希望这是java中的标准功能.
以下是我正在使用的代码:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.xml.namespace.QName;
import javax.xml.soap.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class soaptest {
public static void main(String args[]) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
String url = "http://142.10.10.52:8080/pe/ws/pe/";
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
// Process the SOAP Response
printSOAPResponse(soapResponse);
soapConnection.close();
} catch (Exception e) {
System.err.println("Error occurred while sending SOAP Request to Server");
e.printStackTrace();
}
}
private static SOAPMessage createSOAPRequest() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPElement security = header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse");
usernameToken.addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
SOAPElement username = usernameToken.addChildElement("Username", "wsse");
username.addTextNode("usr");
SOAPElement password = usernameToken.addChildElement("Password", "wsse");
password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
password.addTextNode("pw");
SOAPElement nonce = usernameToken.addChildElement("Nonce", "wsse");
nonce.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
nonce.addTextNode("???");
SOAPElement created = usernameToken.addChildElement("Created", "wsse");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Calendar c1 = Calendar.getInstance();
created.addTextNode(sdf.format(c1.getTime()));
String serverURI = "http://somedomain.com/pe/ws/schema";
envelope.addNamespaceDeclaration("sch", serverURI);
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("EventSubmitRequest", "sch");
SOAPElement soapBodyElem1 = soapBody.addChildElement("Event", "sch");
soapBodyElem.addChildElement(soapBodyElem1);
SOAPElement soapBodyElem2 = soapBodyElem1.addChildElement("EventId", "sch");
soapBodyElem2.addTextNode("392");
SOAPElement soapBodyElem3 = soapBodyElem1.addChildElement("Recoverable", "sch");
soapBodyElem3.addTextNode("false");
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "EventSubmitRequest");
soapMessage.saveChanges();
/* Print the request message */
System.out.print("Request SOAP Message = ");
soapMessage.writeTo(System.out);
System.out.println();
return soapMessage;
}
/**
* Method used to print the SOAP Response
*/
private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
Source sourceContent = soapResponse.getSOAPPart().getContent();
System.out.print("\nResponse SOAP Message = ");
StreamResult result = new StreamResult(System.out);
transformer.transform(sourceContent, result);
}
}
解决方法:
UsernameToken的Oasis reference帮助我填补了一些空白.在这种情况下,第7,8,9页是最合适的.特别是这些部分
/wsse:UsernameToken/wsse:Nonce
This optional element specifies a cryptographically random nonce. Each message
including a element MUST use a new nonce value in order for web
service producers to detect replay attacks.
和
/wsse:UsernameToken/wsse:Nonce/@EncodingType
This optional attribute URI specifies the encoding type of the nonce (see the definition of
for valid values). If this attribute isn’t specified then
the default of Base64 encoding is used.
关于生成’加密随机’随机数,可以建议你使用this answer,然后从中创建一个编码的字符串.在您的情况下,Base64编码,因为这是您在上面的XML请求中使用的encodingType.
标签:java,soap,ws-security,nonce
来源: https://codeday.me/bug/20190623/1275545.html