@tz
根据微信官方回复消息:
1、您更新的只是官方SDK的部分代码,没有完全更新,或者在SDK外还使用了XML的解析没有防XXE
2、您可能有多个回调地址,而你只修复了其中一个
3、您可能有多个服务器,你只发布了其中一台或者修改了没有正式发布
4、实际做xml解析的不是修改的地方
5、xml解析器和httpclient存在多个版本,有冲突,pom.xml可以查看jar版本号。
修改过程;
public final class WXPayXmlUtil {
public static DocumentBuilder newDocumentBuilder(){
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = null;
try {
documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
documentBuilderFactory.setXIncludeAware(false);
documentBuilderFactory.setExpandEntityReferences(false);
documentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
return documentBuilder;
}
public static Document newDocument() {
return newDocumentBuilder().newDocument();
}
/**
* 解析微信发来的请求(XML)
*
* @param request
* @return
* @throws Exception
*/
public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> data = new HashMap<String, String>();
try {
DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
InputStream stream = request.getInputStream();
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
stream.close();
} catch (Exception ex) {
System.out.println("Invalid XML, can not convert to map. Error message: {}.XML content: {}"+ ex.getMessage());
}
return data;
}
/**
* XML格式字符串转换为Map
*
* @param strXML XML字符串
* @return XML数据转换后的Map
* @throws Exception
*/
public static Map<String, Object> parseXml2Map(String strXML) {
Map<String, Object> data = new HashMap<String, Object>();
try {
DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
stream.close();
} catch (Exception ex) {
System.out.println("Invalid XML, can not convert to map. Error message: {}.XML content: {}"+ ex.getMessage()+ strXML);
System.out.println(ex.getMessage());
System.out.println(strXML);
}
return data;
}
/**
* 将Map转换为XML格式的字符串
*
* @param data Map类型数据
* @param rootElement 文件类型
* @return XML格式的字符串
* @throws Exception
*/
public static String parseMap2XML(Map<String, Object> data,String rootElement) {
org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
org.w3c.dom.Element root = document.createElement(rootElement);
document.appendChild(root);
for (String key: data.keySet()) {
String value = String.valueOf(data.get(key));
if (value == null) {
value = "";
}
value = value.trim();
org.w3c.dom.Element filed = document.createElement(key);
filed.appendChild(document.createTextNode(value));
root.appendChild(filed);
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = null;
StringWriter writer = null;
String output = null;
try {
transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
writer.close();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
return output;
}
项目使用部分SDK,直接修改需要对XML转换处理根据SDK更改成自己需要的。仅供参考,目前官方技术人员提示已经修复完成。