- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在尝试在 https 服务器上发送 SOAP 请求时遇到问题。我似乎没有发送任何证书,但我不知道该怎么做。我收到 SSL 握手错误。这是我的源代码。抱歉弄乱了......:)
public class Sign {
static String myToken = "";
static SOAPMessage signedRequest = null;
static SOAPEnvelope soapEnvelope = null;
static String url = "";
static String fileToSend = "";
static String receiptDir = "";
static String jksKey = "";
static String keyPwd = "";
static String privKeyAlias = "";
static TrustManagerFactory tmf = null;
public static void main(String[] args) throws Exception {
try {
url = args[0];
System.out.println(url);
fileToSend = args[1];
System.out.println(fileToSend);
receiptDir = args[2];
System.out.println(receiptDir);
jksKey = args[3];
System.out.println(jksKey);
keyPwd = args[4];
System.out.println(keyPwd);
privKeyAlias = args[5];
System.out.println(privKeyAlias);
} catch (Exception e) {
System.out.println("Paramètres incorrects !");
e.printStackTrace();
}
// Timestamp to use
SimpleDateFormat formater = null;
Date aujourdhui = new Date();
formater = new SimpleDateFormat("yyyyMMddHHmmss");
myToken = formater.format(aujourdhui);
// myToken = "20150112202835";
////////////////////////////
// Constructing the message
////////////////////////////
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
soapEnvelope = soapPart.getEnvelope();
soapEnvelope.removeNamespaceDeclaration(soapEnvelope.getPrefix());
soapEnvelope.setPrefix("soapenv");
soapEnvelope.addNamespaceDeclaration("tem", "http://tempuri.org/");
soapEnvelope.addNamespaceDeclaration("elc",
"http://schemas.datacontract.org/2004/07/ZIRE.Match.Presentation.WebService");
SOAPHeader soapHeader = soapEnvelope.getHeader();
soapHeader.setPrefix("soapenv");
Name nameSecurity = soapEnvelope.createName("Security", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement soapSecurity = soapHeader.addChildElement(nameSecurity);
soapSecurity.addNamespaceDeclaration("wsu",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
Name nameBinSec = soapEnvelope.createName("BinarySecurityToken", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement soapBinSec = soapSecurity.addChildElement(nameBinSec);
soapBinSec.setAttribute("EncodingType",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
soapBinSec.setAttribute("ValueType",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3");
soapBinSec.setAttribute("wsu:Id", "X509-" + myToken);
SOAPBody soapBody = soapEnvelope.getBody();
soapBody.setPrefix("soapenv");
soapBody.addAttribute(
soapEnvelope.createName("id", "wsu",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"),
"id-" + myToken);
soapBody.setIdAttribute("wsu:id", true);
////////////////////////////
// Adding the real content
////////////////////////////
// The real payload new String(readAllBytes(get("test.txt")))
String xmlValue = "<![CDATA[" + readFile(fileToSend, StandardCharsets.UTF_8) + "]]>";
// String xmlValue = "<![CDATA[" + new String(readAllBytes(get(fileToSend))) + "]]>";
// System.out.println(xmlValue);
QName sendMessage = new QName("tem:SendMessage");
QName request = new QName("tem:request");
QName xmldata = new QName("elc:XmlData");
SOAPElement sendMessageNode = soapBody.addChildElement(sendMessage);
SOAPElement requestNode = soapBody.addChildElement(request);
SOAPElement xmldataNode = soapBody.addChildElement(xmldata);
xmldataNode.addTextNode(xmlValue);
requestNode.addChildElement(xmldataNode);
sendMessageNode.addChildElement(requestNode);
Source source = soapPart.getContent();
////////////////////////////////////////////////////////
// Sending the request to the signing function
////////////////////////////////////////////////////////
Node root = ((DOMSource) source).getNode();
signedRequest = addSignature(root.getFirstChild().getOwnerDocument());
////////////////////////////////////////////////////////
// SSL mode configuration
////////////////////////////////////////////////////////
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// Using null here initialises the TMF with the default trust store.
tmf.init((KeyStore) null);
// Get hold of the default trust manager
X509TrustManager defaultTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
defaultTm = (X509TrustManager) tm;
break;
}
}
FileInputStream myKeys = new FileInputStream("D:\\ZIRE\\MesCertificats\\myTrustStore");
// Do the same with your trust store this time
// Adapt how you load the keystore to your needs
KeyStore myTrustStore = KeyStore.getInstance(KeyStore.getDefaultType());
myTrustStore.load(myKeys, "zire2016".toCharArray());
myKeys.close();
tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(myTrustStore);
// Get hold of the default trust manager
X509TrustManager myTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
myTm = (X509TrustManager) tm;
break;
}
}
// Wrap it in your own class.
final X509TrustManager finalDefaultTm = defaultTm;
final X509TrustManager finalMyTm = myTm;
X509TrustManager customTm = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
// If you're planning to use client-cert auth,
// merge results from "defaultTm" and "myTm".
return finalDefaultTm.getAcceptedIssuers();
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
try {
finalMyTm.checkServerTrusted(chain, authType);
} catch (CertificateException e) {
// This will throw another CertificateException if this fails too.
finalDefaultTm.checkServerTrusted(chain, authType);
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
// If you're planning to use client-cert auth,
// do the same as checking the server.
finalDefaultTm.checkClientTrusted(chain, authType);
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { customTm }, null);
// You don't have to set this as the default context,
// it depends on the library you're using.
SSLContext.setDefault(sslContext);
////////////////////////////////////////////////////////
// Sending the request to the receiver
////////////////////////////////////////////////////////
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
// System.setProperty("javax.net.ssl.trustStore", "D:\\ZIRE\\MesCertificats\\myTrustStore" );
// System.setProperty("javax.net.ssl.trustStorePassword", "zire2016");
// System.setProperty("java.net.useSystemProxies", "true");
// SOAPMessage soapResponse = soapConnection.call(signedRequest, url);
// doTrustToCertificates();
SOAPMessage soapResponse = sendMessage(signedRequest, url);
////////////////////////////////////////////////////////
// Processing the response
////////////////////////////////////////////////////////
// Cleaning of the response
ByteArrayOutputStream out = new ByteArrayOutputStream();
soapResponse.writeTo(out);
String strMsg = new String(out.toByteArray());
int d = strMsg.indexOf("<s:Envelope");
int f = strMsg.indexOf("</s:Envelope>") + 13;
String strMsg2 = strMsg.substring(d, f);
// System.out.println(strMsg2);
// Writting of the response on the server
// PrintWriter printWriter = new PrintWriter("D:\\ZIRE\\Result.xml");
// fileToSend
// String receiptFileName = (new File(fileToSend)).getParent() + "Receipt_" + (new File(fileToSend)).getName();
// System.out.println(receiptFileName);
// Writing the response
String receiptFileName = receiptDir + "Receipt_" + (new File(fileToSend)).getName();
System.out.println(receiptFileName);
PrintWriter printWriter = new PrintWriter( receiptFileName );
printWriter.println(strMsg2);
printWriter.close();
soapConnection.close();
}
public static SOAPMessage addSignature(Document contenu)
throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException,
IOException, InvalidAlgorithmParameterException, InstantiationException, IllegalAccessException,
ClassNotFoundException, KeyException, SAXException, ParserConfigurationException, MarshalException,
XMLSignatureException, TransformerException, InvalidKeySpecException, XMLSecurityException, SOAPException {
// Chargement des clés
// FileInputStream is = new FileInputStream("D:\\ZIRE\\Step 1\\mock\\NewJKS.jks");
FileInputStream is = new FileInputStream(jksKey);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, null);
// tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // PKIX
// tmf.init(keystore);
// Enumeration<String> myEnum = keystore.aliases();
// for (Enumeration<String> e = keystore.aliases(); e.hasMoreElements();) {
// String newAlias = e.nextElement();
// System.out.println(newAlias);
// if (newAlias != "wsgbit" ) {
// System.out.println(keystore.getCertificate(newAlias));
// }
// }
// Recup clé privée
// String alias = "wsgbit";
String alias = privKeyAlias;
// Key key = keystore.getKey(alias, "password".toCharArray());
Key key = keystore.getKey(alias, keyPwd.toCharArray());
KeyPair kp = null;
Certificate cert = null;
if (key instanceof PrivateKey) {
// Get certificate of public key
cert = keystore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
// Return a key pair
kp = new KeyPair(publicKey, (PrivateKey) key);
}
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = contenu;
// dumpDocument(doc);
// MAJ du champ wsse:BinarySecurityToken
Element elt = doc.getDocumentElement();
Node myBinSecElt = (Node) (elt.getElementsByTagName("wsse:BinarySecurityToken")).item(0);
myBinSecElt.setTextContent(Utf8.decode(Base64.encode(cert.getEncoded())));
// Debut
org.apache.xml.security.Init.init();
Node mySecElt = (Node) (elt.getElementsByTagName("wsse:Security")).item(0);
org.apache.xml.security.signature.XMLSignature xmlSignature = new org.apache.xml.security.signature.XMLSignature(
doc, "", org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1,
"http://www.w3.org/2001/10/xml-exc-c14n#");
Element eltSign = xmlSignature.getElement();
eltSign.setAttribute("Id", "SIG-" + myToken);
mySecElt.appendChild(eltSign);
Transforms transforms = new Transforms(doc);
transforms.addTransform("http://www.w3.org/2001/10/xml-exc-c14n#");
xmlSignature.addDocument("#id-" + myToken, transforms, Constants.ALGO_ID_DIGEST_SHA1);
SOAPElement myCanonElt = (SOAPElement) (elt.getElementsByTagName("ds:CanonicalizationMethod")).item(0);
InclusiveNamespaces inclusiveNamespaces = new InclusiveNamespaces(doc, "elc soapenv tem");
myCanonElt.appendChild(inclusiveNamespaces.getElement());
SOAPElement mySoapTransform = (SOAPElement) (elt.getElementsByTagName("ds:Transform")).item(0);
InclusiveNamespaces inclusiveNamespaces2 = new InclusiveNamespaces(doc, "elc tem");
mySoapTransform.appendChild(inclusiveNamespaces2.getElement());
// Ajustements
// SOAPElement myCanonElt = (SOAPElement)
// (elt.getElementsByTagName("ds:CanonicalizationMethod")).item(0);
// myCanonElt.setAttribute("Algorithm",
// "http://www.w3.org/2001/10/xml-exc-c14n#");
// Name nameInclusiveNamespaces =
// soapEnvelope.createName("InclusiveNamespaces", "ec",
// "http://www.w3.org/2001/10/xml-exc-c14n#");
// SOAPElement soapInclusiveNamespaces =
// myCanonElt.addChildElement(nameInclusiveNamespaces);
// soapInclusiveNamespaces.setAttribute("PrefixList", "elc soapenv
// tem");
//
// SOAPElement mySoapTransform = (SOAPElement)
// (elt.getElementsByTagName("ds:Transform")).item(0);
// Name nameInclusiveNamespaces2 =
// soapEnvelope.createName("InclusiveNamespaces", "ec",
// "http://www.w3.org/2001/10/xml-exc-c14n#");
// SOAPElement soapInclusiveNamespaces2 =
// mySoapTransform.addChildElement(nameInclusiveNamespaces2);
// soapInclusiveNamespaces2.setAttribute("PrefixList", "elc tem");
//
Name nameKeyInfo = soapEnvelope.createName("KeyInfo", "ds", "http://www.w3.org/2000/09/xmldsig#");
SOAPElement mySoapSign = (SOAPElement) (elt.getElementsByTagName("ds:Signature")).item(0);
SOAPElement soapKeyInfo = mySoapSign.addChildElement(nameKeyInfo);
soapKeyInfo.setAttribute("Id", "KI-" + myToken);
Name nameSecToken = soapEnvelope.createName("SecurityTokenReference", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement soapSecToken = soapKeyInfo.addChildElement(nameSecToken);
soapSecToken.setAttribute("wsu:Id", "STR-" + myToken);
Name nameRef = soapEnvelope.createName("Reference", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement soapNameRef = soapSecToken.addChildElement(nameRef);
soapNameRef.setAttribute("URI", "#X509-" + myToken);
soapNameRef.setAttribute("ValueType",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3");
xmlSignature.sign(key);
// xmlSignature.sign(key);
// dumpDocument(doc);
// String xml = new XMLOutputter().outputString(doc);
// Ecriture du String represantant la requete signée
StringWriter sw = new StringWriter();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
// transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
// transformer.setOutputProperty(OutputKeys.METHOD, "xml");
// transformer.setOutputProperty(OutputKeys.INDENT, "no");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.transform(new DOMSource(doc), new StreamResult(sw));
// String xml = sw.toString(); System.out.println(">>>" + xml + "<<<");
InputStream inputStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));// new
// InputStream(xml);
MessageFactory messageFactory = MessageFactory.newInstance();
return messageFactory.createMessage(null, inputStream);
// Ecriture dans un fichier
// Transformer transformer =
// TransformerFactory.newInstance().newTransformer();
// Result output = new StreamResult(new
// FileOutputStream("D:\\ZIRE\\mySignedFile2.xml"));
// Source input = new DOMSource(doc);
// transformer.transform(input, output);
}
public static String convertToString(Document document) throws TransformerException {
DOMSource domSource = new DOMSource(document);
StringWriter sw = new StringWriter();
Result result = new StreamResult(sw);
// create an instance of TransformerFactory
TransformerFactory transFact = TransformerFactory.newInstance();
Transformer trans = transFact.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
trans.transform(domSource, result);
return sw.toString();
}
private static void dumpDocument(Node root) throws TransformerException {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
// transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(root), new StreamResult(System.out));
}
private static Element getFirstChildElement(Node node) {
Node child = node.getFirstChild();
while ((child != null) && (child.getNodeType() != Node.ELEMENT_NODE)) {
child = child.getNextSibling();
}
return (Element) child;
}
public static Element getNextSiblingElement(Node node) {
Node sibling = node.getNextSibling();
while ((sibling != null) && (sibling.getNodeType() != Node.ELEMENT_NODE)) {
sibling = sibling.getNextSibling();
}
return (Element) sibling;
}
static String readFile(String path, Charset encoding) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
static public SOAPMessage sendMessage(SOAPMessage message, String endPoint) throws SOAPException, IOException {
SOAPMessage result = null;
if (endPoint != null && message != null) {
URL url;
SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
SOAPConnection connection = null;
try {
connection = scf.createConnection(); //point-to-point connection
url = new URL(endPoint);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.connect();
result = connection.call(message, url);
} finally {
if (connection != null) {
try {
connection.close();
} catch (SOAPException soape) {
System.out.print("Can't close SOAPConnection:" + soape);
}
}
}
}
return result;
}
static public void doTrustToCertificates() throws Exception {
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
}
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
}
Wireshark 显示我没有发送证书,尽管我使用的是 JVM 参数,如 -Djavax.net.ssl.keyStore=... 但我想知道 JVM 如何知道我的证书在哪里,因为我可以在 jks 文件中拥有许多证书???
最佳答案
如果您想调用 https 站点,默认情况下您不必发送证书。服务器必须发送,您的客户端将对其进行评估(通过 uri、到期日期、证书链……)。如果证书有效,您的 http 客户端应该默认接受它。
在其他情况下,您可以将服务器的证书导入到本地 keystore (jks),客户端会接受它,因为您永远不会将“不受信任”的证书导入到本地 keystore 。
或者你实现一个类似“谁在乎证书?就去做吧!”的代码(链接:telling java to accept self-signed ssl certificate)。但这不应该在公共(public)/产品环境(如互联网)中使用
关于java - 用java发送soap消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35321529/
我正在使用 SOA 客户端 Firefox 插件向某些 ONVIF 摄像机发送 SOAP 请求。您将在下面看到“GetServices”请求。它对于一台相机工作正常,但对于另一台(AXIS 相机)我收
我正在使用 SOA 客户端 Firefox 插件向某些 ONVIF 摄像机发送 SOAP 请求。您将在下面看到“GetServices”请求。它对于一台相机工作正常,但对于另一台(AXIS 相机)我收
有谁知道 Fiddler 是否可以显示 ASMX Web 服务的原始 SOAP 消息?我正在使用 Fiddler2 和 Storm 测试一个简单的 Web 服务,结果各不相同(Fiddler 显示纯
使用 SOAP 协议(protocol)时,是否可以使用 SOAP 取消挂起的远程函数调用? 我看到三种不同的情况: A) 向需要很长时间才能完成的服务发出请求。例如,当复制包含大量文件的目录时,可以
人们还在写吗SOAP services还是已经通过了它的技术architectural shelf life ?人们是否回归二进制格式? 最佳答案 SOAP 的替代方案不是二进制格式。 我认为您看到了
SOAP 协议(protocol)工作的默认端口号是多少? 最佳答案 没有“SOAP 协议(protocol)”之类的东西。 SOAP 是一种 XML 模式。 但是,它通常通过 HTTP(端口 80)
之间有什么区别 和 以及如何在它们之间切换? 如何将响应从 具有定义的命名空间 "http://schemas.xmlsoap.org/soap/envelope/" ,它的特殊含义是底层 XML
我正在从 Mule 进行 SOAP 调用。我正在使用 default-exception-strategy 来捕获异常。发生异常时,如何发送我自己的故障代码和故障字符串而不是通用的 soap 故障消息
我正在编写一个 powershell 脚本,它将每 10 分钟 ping 一次soap web 服务,以使其保持活跃状态,从而提高性能。我们已经在 IIS 中尝试了多种技术,应用程序池空闲超时和只
如有任何帮助,我们将不胜感激;我已经研究了几天了。 下面是我目前得到的代码;不幸的是,当我运行它时出现 HTTP 415 错误; 无法处理消息,因为内容类型为“text/xml; charset=UT
我们需要使用其他团队开发的网络服务。使用 JAX-WS用于生成网络服务。我们正在使用 wsimport 生成客户端 stub 。 问题是我需要将以下信息作为 header 与 SOAP 正文一起传递:
我的意思是,真正的互操作:从 Java 到 .NET,从 PHP 到 Java,等等。 我之所以这样问,是因为我们的权力希望我们使用 SOAP Web 服务实现面向公众的 API,并且我试图强调支持
我写了一个拦截器进行测试。但是我在Interceptor中获得的Soap消息正文始终为null。 我的Cxf是Apache-CXF-2.4.0 bean.xml是这样的:
我正在尝试查询货币的 netsuite api。以下soap请求在SOAP UI客户端中对我有用。但是我很难尝试使用 ruby 的 savon gem 0.9.7 版进行相同的工作。
我创建了一个示例 Mule 流,首先根据 http://www.mulesoft.org/documentation/display/current/Consuming+Web+Services+wi
我正在尝试使用此 SOAP 服务:http://testws.truckstop.com:8080/v13/Posting/LoadPosting.svc?singleWsdl使用 node-soap
我有几个 SoapUI 测试步骤,其中响应返回空(即“-> 空/空响应”),这正是我所期望的。 如何断言对测试步骤请求的响应为空? 到目前为止,我已经尝试了以下但没有运气: 审查可用的断言,无需定制
我正在尝试构建一个手动 HTTP 请求,以便从我认为是相当简单的 SOAP Web 服务调用中返回响应。但是,我无法正确构建请求,并且没有得到我期望的响应。 适用wsdl声明: wsdl 目标命名空间
我正在尝试使用 Insomnia 调用 SOAP 电话 - 特别是试图让帖子成功。我将 URL 定义为端点,并将正文类型作为带有 SOAP 内容(信封、标题、正文)的 XML。我在标题中定义了用户 I
我正在学习 SOAP 实现,并且对于 SOAP 1.2 信封的适当 namespace URI 感到有些困惑。 w3c specification for SOAP指的是“http://www.w3.
我是一名优秀的程序员,十分优秀!