我在验证WebService上的某些XML输入数据时遇到问题。我包含了重现错误所需的一切,所以希望有人能够帮助我。提前谢谢!
我有一些黑客向我的公共界面发送了一些无效的XML,而不是在我的XSD验证中检测到它,它甚至在它进入XSD之前崩溃整个IIS WebApp,而我无法解决它!这是他发送的XML:
<?xml version="1.0"?>
<Security xmlns="">
<SecurityPermissions>
<SecurityPermission ActionID="90" Value="1"></SecurityPermission>
<SecurityPermission ActionID="80" Value="1"></SecurityPermission>
</SecurityPermissions>
<C><C><C><C><C>...</C></C></C></C></C>
</Security>
无效的是嵌套的&lt; C&gt; 节点。我在这里缩短了XML,但它们就像 1000 级别一样。
有关完整的XML,请下载 HERE 。
对于XSD文件,请下载 HERE 。
这是XSD架构:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema targetNamespace="UpdatePermissions.xsd" xmlns="UpdatePermissions.xsd" xmlns:mstns="UpdatePermissions.xsd" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xs:element name="Security">
<xs:complexType>
<xs:sequence>
<xs:element name="SecurityPermissions" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="SecurityPermission" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="ActionID" type="xs:int" use="required" />
<xs:attribute name="Value" type="xs:int" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
由于XML输入有xmlns =“”(这就是我所有客户端都传递它的方式),我不得不用新的xmlns值修改输入的XML(我把它设置为xmlns =“UpdatePermissions.xsd” “)以便XSD验证起作用。由于您不能只在现有的XmlElement上设置xmlns,我必须将XML复制到XmlDocumentFragment。这与嵌套节点一起使我的应用程序崩溃,而StackOverflowException无法在try..catch中捕获。这是它的样子:
[WebMethod]
public XmlElement UpdatePermissions(XmlElement xInput)
{
var errors = ValidateUpdatePermissionsXml(xInput);
if (errors.Count > 0)
throw new Exception(" I hate everything");
// do other processing
return xInput;
}
public List<string> ValidateUpdatePermissionsXml(XmlElement xInput)
{
// set xmlns since it isn't provided by caller but we need it to validate against XSD
xInput.SetAttribute("xmlns", "UpdatePermissions.xsd");
// transfer XML to a fragment otherwise xmlns attribute we set wouldn't take effect
var fragment = xInput.OwnerDocument.CreateDocumentFragment();
var xmlString = xInput.OuterXml; // <---- THIS IS WHERE THE APP CRASHES
fragment.InnerXml = xmlString;
//setup errors array
var errors = new List<string>();
//read in schema
var schemaStream = File.OpenRead(@"c:\UpdatePermissions.xsd");
var schema = XmlSchema.Read(schemaStream, null);
var schemaSet = new XmlSchemaSet();
schemaSet.Add(schema);
//setup validation settings
var readerSettings = new XmlReaderSettings();
readerSettings.ValidationType = ValidationType.Schema;
readerSettings.Schemas = schemaSet;
readerSettings.ValidationEventHandler += (s, e) => errors.Add(e.Exception.Message);
//create readers
var nodeReader = new XmlNodeReader(fragment);
var reader = XmlReader.Create(nodeReader, readerSettings);
//read
while (reader.Read()) ;
return errors;
}
这是我的单元测试总是失败:
[TestMethod]
public void TestXSDValidation_Invalid_DeeplyNestedNodes()
{
//load Xml from file into XmlElement
var badXml = File.ReadAllText(@"c:\UpdatePermissions_BadRequest.xml");
var doc = new XmlDocument();
doc.LoadXml(badXml);
var badElement = doc.DocumentElement;
var errors = ValidateUpdatePermissionsXml(badElement);
Assert.AreEqual(1, errors.Count);
Assert.AreEqual("The element 'SecurityPermissions' in namespace 'UpdatePermissions.xsd' has invalid child element 'C' in namespace 'UpdatePermissions.xsd'. List of possible elements expected: 'SecurityPermission' in namespace 'UpdatePermissions.xsd'.", errors[0]);
}
由于嵌套节点的深度,对.OuterXml的调用似乎因StackOverflowException而失败。我通过其他方式将XML写入字符串的所有尝试都失败了。
我无法弄清楚的是我如何接受具有EMPTY xmlns属性值的XML,并且仍然可以在不必将XML复制到片段的情况下进行验证。我试过的一切都以某种方式写出XML失败并使应用程序崩溃。试试吧,你会明白我的意思!
答案 0 :(得分:0)
而不是尝试将整个请求转换为字符串,而不是使用请求流的XmlTextReader解析xml?这里有一篇文章提供了这个课程的更多细节: