一 使用xsd模式文件验证xml文件

xml文件:

<?xml version="1.0" encoding="utf-8" ?>
<Books>
<Book>
<Title>ExampleTitle</Title>
<Author>John Smith</Author>
<Pages>500</Pages>
</Book>
<Book>
<Title>Another Title</Title>
<Author>John Doe</Author>
<Pages>250</Pages>
</Book>
</Books>

xsd文件:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Books">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Book">
<xs:complexType>
<xs:sequence>
<xs:element name="Title" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="Author" type="xs:string" />
<xs:element name="Pages" type="xs:unsignedShort" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

验证代码:

   static bool XmlValidate(string xmlPath, string xsdPath, out string message)
{
bool isXmlValid = true;
string errorMessage = string.Empty;
XmlReaderSettings settings = new XmlReaderSettings()
{
ValidationType = ValidationType.Schema,
ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings
};
settings.ValidationEventHandler += (o, e) =>
{
isXmlValid = false;
errorMessage = e.Message;
};
XmlSchema schema = XmlSchema.Read(new StreamReader(xsdPath), null);
settings.Schemas.Add(schema);
XmlDocument xmlDocument = new XmlDocument();
XmlReader xmlReader = XmlReader.Create(xmlPath, settings);
xmlDocument.Load(xmlReader);
message = errorMessage;
return isXmlValid;
}

调用代码:

string xmlPath = "books.xml";
            string xsd = "books.xsd";
            string message = string.Empty;
            bool validate = XmlValidate(xmlPath, xsd, out message);

xml查询时需要注意XQuery注入(XPath注入),通常xPath语句如下:

static string GetBookTitle(string author, int page)
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("books.xml");
XPathNavigator navigator = xmlDocument.CreateNavigator();
string xquery = string.Format("string(//Book[Author/text()='{0}' and Pages/text()={1}]/Title/text())", author, page.ToString());
XPathExpression expression = navigator.Compile(xquery);
return navigator.Evaluate(expression).ToString();
}

但是这样的代码很容易遭到攻击,这里我们用Mvp.xml(开源库http://mvpxml.codeplex.com/)来实现参数化查询,防止xquery注入。

修改后的代码:

   static string GetBookTitle(string author, int page)
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("books.xml");
string xquery = "string(//Book[Author/text()=$author and Pages/text()=$page]/Title/text())";
XPathNavigator navigator = xmlDocument.CreateNavigator();
XPathExpression expression = DynamicContext.Compile(xquery); DynamicContext ctx = new DynamicContext();
ctx.AddVariable("author", author);
ctx.AddVariable("page",page.ToString());
expression.SetContext(ctx); return navigator.Evaluate(expression).ToString();
}

采用对称加密,加密xml节点新建xml文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<envelope>
<to>ma.jiang@wipro.com</to>
<from>gavin_ma@vfc.com</from>
<message>You have just been paid.</message>
</envelope>

加密和解密代码如下:

  static void Encrypt(XmlDocument document, string elementNameToEntrypt, SymmetricAlgorithm algorithm)
{
if (document == null)
throw new ArgumentNullException("document");
if (elementNameToEntrypt == null)
throw new ArgumentNullException("elementNameToEntrypt");
if (algorithm == null)
throw new ArgumentNullException("key");
XmlElement elementToEncrypt = document.GetElementsByTagName(elementNameToEntrypt)[0] as XmlElement;
if (elementToEncrypt == null)
throw new XmlException("The specified element was not found");
EncryptedXml exml = new EncryptedXml(); byte[] encryptedElement = exml.EncryptData(elementToEncrypt, algorithm, false);
EncryptedData encryptedData = new EncryptedData { Type = EncryptedXml.XmlEncElementUrl };
string encryptionMethod = string.Empty;
if (algorithm is TripleDES)
encryptionMethod = EncryptedXml.XmlEncTripleDESUrl;
else if (algorithm is DES)
encryptionMethod = EncryptedXml.XmlEncDESUrl;
else if (algorithm is Rijndael)
{
switch (algorithm.KeySize)
{
case 128:
encryptionMethod = EncryptedXml.XmlEncAES128Url;
break;
case 192:
encryptionMethod = EncryptedXml.XmlEncAES192Url;
break;
case 256:
encryptionMethod = EncryptedXml.XmlEncAES256Url;
break;
}
}
else
{
throw new CryptographicException("Specificed algorithm is not supported");
}
encryptedData.EncryptionMethod = new EncryptionMethod(encryptionMethod);
encryptedData.CipherData.CipherValue = encryptedElement;
EncryptedXml.ReplaceElement(elementToEncrypt, encryptedData, false);
}
static void Decrypt(XmlDocument document, SymmetricAlgorithm algorithm)
{
if (document == null)
throw new ArgumentNullException("document"); if (algorithm == null)
throw new ArgumentNullException("key");
XmlElement encryptedElement = document.GetElementsByTagName("EncryptedData")[0] as XmlElement;
if (encryptedElement == null)
throw new XmlException("No encrypted element was found.");
EncryptedData encryptedData = new EncryptedData();
encryptedData.LoadXml(encryptedElement);
EncryptedXml encryptedXml = new EncryptedXml();
byte[] rgbOutput = encryptedXml.DecryptData(encryptedData, algorithm);
encryptedXml.ReplaceData(encryptedElement,rgbOutput);
}

调用方法如下:

string xmlPath = "encrypt.xml";
            XmlDocument document = new XmlDocument();
            document.Load(xmlPath);
            RijndaelManaged rijndael = new RijndaelManaged();
            Encrypt(document, "message", rijndael);
            Decrypt(document, rijndael);

加密后的数据如图:

采用非对成加密技术,加密xml节点

加密和解密代码如下:

  public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, string EncryptionElementID, RSA Alg, string KeyName)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
if (ElementToEncrypt == null)
throw new ArgumentNullException("ElementToEncrypt");
if (EncryptionElementID == null)
throw new ArgumentNullException("EncryptionElementID");
if (Alg == null)
throw new ArgumentNullException("Alg");
if (KeyName == null)
throw new ArgumentNullException("KeyName"); ////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElemnt object.
////////////////////////////////////////////////
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement; // Throw an XmlException if the element was not found.
if (elementToEncrypt == null)
{
throw new XmlException("The specified element was not found"); }
RijndaelManaged sessionKey = null; try
{
//////////////////////////////////////////////////
// Create a new instance of the EncryptedXml class
// and use it to encrypt the XmlElement with the
// a new random symmetric key.
////////////////////////////////////////////////// // Create a 256 bit Rijndael key.
sessionKey = new RijndaelManaged();
sessionKey.KeySize = 256; EncryptedXml eXml = new EncryptedXml(); byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);
////////////////////////////////////////////////
// Construct an EncryptedData object and populate
// it with the desired encryption information.
//////////////////////////////////////////////// EncryptedData edElement = new EncryptedData();
edElement.Type = EncryptedXml.XmlEncElementUrl;
edElement.Id = EncryptionElementID;
// Create an EncryptionMethod element so that the
// receiver knows which algorithm to use for decryption. edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
// Encrypt the session key and add it to an EncryptedKey element.
EncryptedKey ek = new EncryptedKey(); byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, Alg, false); ek.CipherData = new CipherData(encryptedKey); ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url); // Create a new DataReference element
// for the KeyInfo element. This optional
// element specifies which EncryptedData
// uses this key. An XML document can have
// multiple EncryptedData elements that use
// different keys.
DataReference dRef = new DataReference(); // Specify the EncryptedData URI.
dRef.Uri = "#" + EncryptionElementID; // Add the DataReference to the EncryptedKey.
ek.AddReference(dRef);
// Add the encrypted key to the
// EncryptedData object. edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
// Set the KeyInfo element to specify the
// name of the RSA key. // Create a new KeyInfoName element.
KeyInfoName kin = new KeyInfoName(); // Specify a name for the key.
kin.Value = KeyName; // Add the KeyInfoName element to the
// EncryptedKey object.
ek.KeyInfo.AddClause(kin);
// Add the encrypted element data to the
// EncryptedData object.
edElement.CipherData.CipherValue = encryptedElement;
////////////////////////////////////////////////////
// Replace the element from the original XmlDocument
// object with the EncryptedData element.
////////////////////////////////////////////////////
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
}
catch (Exception e)
{
// re-throw the exception.
throw e;
}
finally
{
if (sessionKey != null)
{
sessionKey.Clear();
} } } public static void Decrypt(XmlDocument Doc, RSA Alg, string KeyName)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
if (Alg == null)
throw new ArgumentNullException("Alg");
if (KeyName == null)
throw new ArgumentNullException("KeyName"); // Create a new EncryptedXml object.
EncryptedXml exml = new EncryptedXml(Doc); // Add a key-name mapping.
// This method can only decrypt documents
// that present the specified key name.
exml.AddKeyNameMapping(KeyName, Alg); // Decrypt the element.
exml.DecryptDocument(); }

代码调用如下:

string xmlPath = "encrypt.xml";
            XmlDocument document = new XmlDocument();
            document.PreserveWhitespace = true;
            document.Load(xmlPath);
            UnicodeEncoding ByteConverter = new UnicodeEncoding();
            CspParameters cspParams = new CspParameters { KeyContainerName = "XML_ENC_RSA_KEY" };
            using ( RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams))
            {
                Encrypt(document, "message", "EncryptedElementID", rsaKey, "rsaKey");
                // document.Save("test.xml");
                     Decrypt(document, rsaKey, "rsaKey");
            };

运行结果如图:

 用非对称密钥签名xml

实现代码如下:

  static void SignXml(XmlDocument document, RSA algorithm)
{
SignedXml signxml = new SignedXml(document) { SigningKey = algorithm };
Reference reference = new Reference { Uri = string.Empty };
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
signxml.AddReference(reference);
signxml.ComputeSignature();
XmlElement xmlDigitalSignature = signxml.GetXml();
document.DocumentElement.AppendChild(document.ImportNode(xmlDigitalSignature,true));
}
static bool IsSignedXmlValid(XmlDocument document, RSA algorithm)
{
SignedXml signxml = new SignedXml(document);
XmlNodeList nodelist = document.GetElementsByTagName("Signature");
if (nodelist.Count < )
{
throw new CryptographicException("No signature found");
}
signxml.LoadXml((XmlElement)nodelist[]);
return signxml.CheckSignature(algorithm);
}

调用代码如下:

string xmlPath = "encrypt.xml";
            XmlDocument document = new XmlDocument();
            document.PreserveWhitespace = true;
            document.Load(xmlPath);
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            SignXml(document, rsa);
            IsSignedXmlValid(document, rsa);

运行结果如图:

个人认为证书在xml中使用情况不常见,并且也比较简单,这里就省略了。

总结一下:

在使用xml之前,必须使用严格的架构(模式文件)来验证,尽可能使用架构的本地副本,以便缓存解析器来缓存他们。

选择一个合适的加密算法,如果应用程序需要加密和解密相同的应用程序,那么选择对称加密;应用程序需要和外部系统进行交流,那么选择非对称加密。

如果需要确保数据没有被更改,就需要始终使用数字签名

C# xml 常规 保护 方法总结的更多相关文章

  1. C#中常用的几种读取XML文件的方法

    1.C#中常用的几种读取XML文件的方法:http://blog.csdn.net/tiemufeng1122/article/details/6723764/

  2. 八、Android学习第七天——XML文件解析方法(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 八.Android学习第七天——XML文件解析方法 XML文件:exten ...

  3. 解析Xml四种方法

    关键字:Java解析xml.解析xml四种方法.DOM.SAX.JDOM.DOM4j.XPath [引言] 目前在Java中用于解析XML的技术很多,主流的有DOM.SAX.JDOM.DOM4j,下文 ...

  4. C#中经常使用的几种读取XML文件的方法

    XML文件是一种经常使用的文件格式,比如WinForm里面的app.config以及Web程序中的web.config文件,还有很多重要的场所都有它的身影.Xml是Internet环境中跨平台的,依赖 ...

  5. Flex中操作XML的E4X方法

    用于处理 XML 的 E4X 方法 Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本   ECMAScript for XML 规范定义了一组用于使用 XML 数据的类 ...

  6. Spring保护方法

    Spring保护方法 一.使用注解保护方法 1.@Secured 由Spring Security提供,首先需要启用基于注解的方法安全性: @EnableGlobalMethodSecurity(se ...

  7. 微软BI 之SSIS 系列 - 两种将 SQL Server 数据库数据输出成 XML 文件的方法

    开篇介绍 在 SSIS 中并没有直接提供从数据源到 XML 的转换输出,Destination 的输出对象有 Excel File, Flat File, Database 等,但是并没有直接提供 X ...

  8. 【重要】U3D存放本地游戏存档——不同平台载入XML文件的方法——IOS MAC Android

    在PC上和IOS上读取XML文件的方式略有差别,经测试,IOS上不支持如下方法载入XML文件: XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load( ...

  9. (转)U3D不同平台载入XML文件的方法——IOS MAC Android

    自:http://www.cnblogs.com/sifenkesi/archive/2012/03/12/2391330.html 在PC上和IOS上读取XML文件的方式略有差别,经测试,IOS上不 ...

随机推荐

  1. JDBC之批处理

    JDBC之批处理 现在有这么一个需求,要求把2000条记录插入表中,如果使用java代码来操作,我们可以使用Statement或者PreparedStatement来实现,通过循环来把SQL语句一条又 ...

  2. [Luogu5241]序列(DP)

    固定一种构造方法,使它能够构造出所有可能的序列. 对于一个要构造的序列,把所有点排成一串,若a[i]=a[i-1],那么从1所在弱连通块往连通块后一个点连,若所有点都在一个连通块里了,就在1所在强连通 ...

  3. 得到某个android应用 的POST和GET请求的 网址和参数

    两种思路: 1.用笔记本建个wifi热点,然后抓包. 2. 把APK装到模拟器上 会在任务管理中有个exe进程,用一个软件可以抓取这个进程的所有请求 .

  4. PHP 图像居中裁剪函数

    图像居中裁减的大致思路: 1.首先将图像进行缩放,使得缩放后的图像能够恰好覆盖裁减区域.(imagecopyresampled — 重采样拷贝部分图像并调整大小) 2.将缩放后的图像放置在裁减区域中间 ...

  5. Python生成requirements.txt包依赖管理文件

    requirements.txt是Python的依赖管理软件,和Java的POM一样. requirements.txt会生成使用了pip安装后的依赖包,在正常环境下会生成这个目录下的包/usr/lo ...

  6. centos ssh终端下高亮显示git分支名

    #set git branch green=$'\e[1;32m' magenta=$'\e[1;35m' normal_colours=$'\e[m' function find_git_branc ...

  7. cocos2d-x学习资源汇总

      http://blog.csdn.net/akof1314 http://blog.csdn.net/bill_man/ http://blog.csdn.net/fylz1125/ MoonWa ...

  8. 计算机意外地重新启动或遇到错误。windows安装无法继续。若要安装windows 请单击 确定 重新启动计算机

    快安装完系统时遇到提示:计算机意外地重新启动或遇到错误.Windows 安装无法继续.若要安装Windows,请单击“确定”重新启动计算机,然后重新启动安装”.如下图所示: 解决办法: 当出现如上提示 ...

  9. 一步一步学习ASP.NET 5 (一)-基本概念和环境配置

    编者语:时代在变,在csdn开博一年就发了那么的两篇文章.不管是什么原因都认为有愧了.可是今年重心都会在这里发表一些文章,和大家谈谈.NET, 移动跨平台,云计算等热门话题.希望有更好的交流. 好吧言 ...

  10. tms web core程序部署

    tms web core程序部署 笔者把已经开发好的TMS WEB CORE程序部署到阿里云服务器上面,来作为例子. 1)复制TMS WEB CORE前端程序到服务器的c:\room\ 2)复制TMS ...