<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-陋室铭</title><link>http://www.cnblogs.com/cuihongyu3503319/</link><description>
                永远也不要停下学习的脚步(大道至简至易)
   
   
</description><language>zh-cn</language><lastBuildDate>Sat, 26 Jul 2008 06:33:04 GMT</lastBuildDate><pubDate>Sat, 26 Jul 2008 06:33:04 GMT</pubDate><ttl>60</ttl><item><title>使用 .NET Framework 2.0 在您的应用程序中支持证书(转)</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/25/1251373.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Fri, 25 Jul 2008 07:03:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/25/1251373.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1251373.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/25/1251373.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1251373.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1251373.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<div class="FeatureByLine">Dominick Baier</div>
<div><br />
<table>
    <tr valign="top">
            <td><span class="CodeDownloadText">本文讨论: </span>
            <ul>
                <li class="ListingBullet">Windows 证书存储区</li>
                <li class="ListingBullet">.NET 中的证书类</li>
                <li class="ListingBullet">验证、SSL、Web 服务和代码签名</li>
                <li class="ListingBullet">对数据进行签名和加密 </li>
            </ul>
            </td>
            <td><span class="CodeDownloadText">本文使用了以下技术: </span><br />
            .NET Framework 2.0<br />
            </td>
        </tr>
    </table>
<div class="ContentSeparator">
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109036">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109036_h"><img id="ctl00_ContentPlaceHolder1_cpe109036_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/minus.gif"  alt="" />&nbsp;目录 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109036_c" style="display: block; overflow: hidden; width: auto; height: auto" olddisplay="null">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none"><a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S1">如何获得一个证书</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S2">Windows 证书存储区</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S3">使用证书</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S4">访问证书</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S5">显示证书详细信息和证书选择器</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S6">验证证书</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S7">SSL 支持</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S8">Web 服务安全性</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S9">安全策略和代码签名</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S10">ClickOnce 清单</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S11">对数据进行签名和加密</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S12">解密数据和验证签名</a> <br />
<a href="http://msdn.microsoft.com/zh-cn/magazine/cc163454.aspx#S13">综述</a> <br />
</div>
</div>
</div>
<div class="ArticleNormalPara">证书在 Microsoft<span class="superscript">&#174;</span> .NET Framework 中应用十分广泛，从安全通信到代码签名再到安全策略。.NET Framework 2.0 改进了对证书的支持，为使用证书进行符合标准的加密操作添加了一个全新的命名空间。在本文中，我将讨论证书和 Windows<span class="superscript">&#174;</span> 证书存储区的背景知识。同时我还会为您介绍证书 API 的使用方法和 Framework 如何使用这些 API 实现安全功能。</div>
<div class="ArticleNormalPara">&#8220;证书&#8221;实际上是一种 ASN.1 (Abstract Syntax Notation One) 编码的文件，它包含一个公钥和其他有关该密钥及其所有者的信息。另外，证书具有有效期，并通过另一密钥（所谓的颁发者）进行签名，该密钥能保证这些属性的真实性，最重要的是，保证公钥本身的真实性。您可以将 ASN.1 看成是一种二进制 XML。与 XML 一样，它也具有编码规则、强类型和标记；但是，这些都是二进制值，通常没有可打印字符与之对应。</div>
<div class="ArticleNormalPara">要使这种文件能够在系统之间互换，需要一种标准的格式。这种标准格式即 X.509（当前为第 3 版），RFC 3280 (<a href="http://tools.ietf.org/html/rfc3280">tools.ietf.org/html/rfc3280</a>) 中对其进行了描述。虽然 X.509 并未规定证书中嵌入的密钥类型，但 RSA 算法是目前使用最为普遍的非对称加密算法。</div>
<div class="ArticleNormalPara">首先让我们回顾一下这种算法的历史由来。&#8220;RSA&#8221;这一名称是发明该算法的三个人的姓氏首字母缩写：Ron Rivest、Adi Shamir 和 Len Adleman。他们成立了一家名为 RSA Security 的公司，该公司发布了几个名为公钥加密标准 (PKCS) 的标准文档。这些文档对加密技术的几个方面进行了介绍。</div>
<div class="ArticleNormalPara">其中最流行的文档之一，即 PKCS #7，为已签名和加密的数据定义了一种名为加密消息语法 (CMS) 的二进制格式。目前 CMS 广泛应用于众多流行的安全协议，其中包括安全套接字层 (SSL) 和安全多用途 Internet 邮件扩展 (S/MIME)。由于它是一种标准，因此当应用程序需要在几方之间交换已签名和加密的数据时，它也是一种可供选择的格式。您可以从 RSA Laboratories 网站 (<a href="http://www.rsasecurity.com/rsalabs/node.asp?id=2124">www.rsasecurity.com/rsalabs/node.asp?id=2124</a>) 获得这些 PKCS 文档。</div>
<br />
<div class="ArticleTypeTitle" id="S1">如何获得一个证书</div>
<div class="ArticleNormalPara">目前有几种方法可以获取证书。在交换文件时，证书通常以两种格式之一出现。扩展名为 .cer 的文件是采用 X.509v3 格式的已签名 ASN.1 文件。这些文件中包含着我之前提到的一个公钥和额外的信息。您要将这些文件中包含的内容提供给业务合作伙伴或朋友，以便他们能够使用公钥为您加密数据。</div>
<div class="ArticleNormalPara">此外，您可能会遇到扩展名为 .pfx（个人信息交换，Personal Information Exchange）的文件。.pfx 文件包含一个证书和与之对应的私钥（PKCS #12 标准对该格式有所说明）。这类文件是高度敏感的，通常用于导入服务器上的密钥对或用于备份目的。在导出密钥对时，Windows 提供用密码加密 .pfx 文件；而在导入密钥对时，您必须再次提供此密码方可导入。</div>
<div class="ArticleNormalPara">您还可以生成自己的证书。证书的生成方式通常取决于其使用方式。在对等方身份不明的常规 Internet 环境下，您通常要向某个商业证书颁发机构 (CA) 申请证书。该方法的优点在于这些已知的 CA 已经得到 Windows 和其他任何支持证书及 SSL 的 OS（包括浏览器）的信任。因此不必进行 CA 密钥的交换。</div>
<div class="ArticleNormalPara">对于 B2B 和 Intranet 环境，您可以使用内部 CA。Windows 2000 和 Windows Server<span class="superscript">&#174;</span> 2003 中包含了证书服务。配合 Active Directory<span class="superscript">&#174;</span> 一起使用，此功能允许您在组织内轻松地分发证书。（稍后我将介绍如何从私有 CA 申请证书。）</div>
<div class="ArticleNormalPara">在开发过程中，有时您可能会发现，刚才提到的方法不起作用了。例如，如果您出于测试的需要希望很快获得一个证书，可以使用 makecert.exe。该工具包随附于 .NET Framework SDK 中，能够生成证书和密钥对。在 IIS 资源工具包中也有一个与之类似的名为 selfssl.exe 的工具。它专门用于创建 SSL 密钥对，而且使用这种密钥，只需一个步骤即可对 IIS 进行配置。</div>
<br />
<div class="ArticleTypeTitle" id="S2">Windows 证书存储区</div>
<div class="ArticleNormalPara">证书和与之对应的私钥可存储在各种设备上，例如硬盘、智能卡和 USB 令牌。Windows 提供了一个名为证书存储区的抽象层，用于统一证书的访问方式，不管这些证书存储在何处。只要硬件设备具有 Windows 支持的加密服务提供程序 (CSP)，就可以使用证书存储区 API 访问其上存储的数据。</div>
<div class="ArticleNormalPara">证书存储区位于用户配置文件的深处。这样就可以对特定帐户的密钥使用 ACL。每个存储区被划分为若干个容器。例如，其中有一个名为 Personal 的容器，您可以将自己的证书（具有关联私钥的证书）存储在其中。Trusted Root Certification Authorities 容器包含了所有您信任的 CA 的证书。Other People 容器则保存着与您进行安全通信的人员的证书。此外还有其他一些证书。访问证书存储区最简单方法是运行 certmgr.msc。</div>
<div class="ArticleNormalPara">另外还有一个供 Windows 计算机帐户（NETWORK、LOCAL SERVICE 和 LOCAL SYSTEM） 使用的计算机范围的存储区，如果您希望跨帐户共享证书或密钥，可以使用该存储区。 ASP.NET 应用程序总是使用计算机存储区；而对于桌面应用程序，证书通常安装在用户存储区。 </div>
<div class="ArticleNormalPara">只有管理员才能对计算机存储区和服务帐户存储区进行管理。要实现这一目的，您必须启动 Microsoft 管理控制台 (mmc.exe) 并添加&#8220;证书&#8221;管理单元，从中可以选择要管理的存储区。<strong>图 1</strong> 显示了 MMC 管理单元的一个屏幕快照。</div>
<div class="ArticleImageSpacer"><img onmouseover="this.style.cursor='pointer';" style="cursor: pointer" onclick="var large='http://i.msdn.microsoft.com/cc163454.certificatesfig01_L.gif'; var small='http://i.msdn.microsoft.com/cc163454.certificatesfig01.gif'; var current=this.src;  if (current.indexOf(large) > 0) this.src=small; if (current.indexOf(small) > 0)this.src=large;" alt="" src="http://i.msdn.microsoft.com/cc163454.certificatesfig01.gif">
<div class="ArticleImageCaptionText">图 1<strong>&nbsp;&#8220;证书&#8221;MMC 管理单元&nbsp;</strong>(单击该图像获得较大视图)</div>
</div>
<div class="ArticleNormalPara">除了可以导入、导出和搜索证书外，您还可以通过管理单元从内部企业 CA 申请证书。只需右键单击 Personal 容器并选择 All Tasks | Request Certificate。本地计算机会随后生成一个 RSA 密钥对，并将公钥部分发送给 CA 以进行签名。Windows 将已签名的证书添加到证书存储区，并将对应的私钥添加到密钥容器。证书通过存储属性被链接到密钥容器。</div>
<div class="ArticleNormalPara">对于对应帐户或 LOCAL SYSTEM，私钥容器受到 ACL 的严密保护。当您要从 ASP.NET 或其他用户帐户访问计算机配置文件中存储的密钥时，这就成为一个问题。为此我编写了一个工具，您可以用它修改容器文件的 ACL （可从 <a href="http://www.leastprivilege.com/HowToGetToThePrivateKeyFileFromACertificate.aspx">www.leastprivilege.com/HowToGetToThePrivateKeyFileFromACertificate.aspx</a> 下载该工具）。</div>
<div class="ArticleNormalPara">商业 CA 和 Windows CA 还为申请证书提供了 Web 界面。通常在这些时候，由 Internet Explorer<span class="superscript">&#174;</span> 中的 ActiveX<span class="superscript">&#174;</span> 控件生成密钥并将其导入当前用户的存储区中。按照惯例，当您想指定某个证书可以由某个用户或服务访问时，有以下两种选择：一是将该证书导入该用户的存储区，二是在以该用户身份登录时申请证书。</div>
<br />
<div class="ArticleTypeTitle" id="S3">使用证书</div>
<div class="ArticleNormalPara">证书可用于 .NET Framework 中的各个位置，而且在某种程度上此功能依赖于 System.Security.X509Certificates 命名空间中的 X509Certificate 类。如果您更仔细地观察，还会发现证书类是以 2 结尾。这是因为 .NET Framework 1.x<em> 具有一个名为 X509Certificate 的 X.509 证书表示形式。该类的功能有限，而且不支持加密操作。2.0 版中新添加了一个名为 X509Certificate2 的类。该类派生自 X509Certificate，同时添加了许多功能。您可以根据需要在二者之间来回转换，但无论何时都应尽可能使用最新版本。</div>
<br />
<div class="ArticleTypeTitle" id="S4">访问证书</div>
<div class="ArticleNormalPara">您可以直接从文件系统检索证书。但更好的办法是从证书存储区进行检索。要从一个 .cer 文件创建一个 X509Certificate2 实例，只需将文件名传递给构造函数即可：
<div class="" id="ctl00_ContentPlaceHolder1_ctl04_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl04');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl04" space="preserve">X509Certificate2 cert1 = new X509Certificate2("alice.cer");
</pre>
</div>
</div>
<div class="ArticleNormalPara">您也可以从 .pfx 文件加载证书。但是，如前所述，.pfx 文件可以通过设置密码加以保护，因此您应当将该密码以 SecureString 的形式提供给他人。SecureString 在内部对密码进行加密，并尽可能降低密码在内存、页面文件和崩溃转储期间的暴露几率。因此，您每次只能向字符串添加一个（值类型）字符。如果要从控制台要求用户提供密码，那么<strong>图 2</strong> 中的代码是非常有用的，这些代码可禁用控制台回显并返回 SecureString。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109037">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109037_h"><img id="ctl00_ContentPlaceHolder1_cpe109037_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;2&nbsp;从控制台申请密码 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109037_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl08_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl08');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl08" space="preserve">private SecureString GetSecureStringFromConsole()
{
SecureString password = new SecureString();
Console.Write("Enter Password: ");
while (true)
{
ConsoleKeyInfo cki = Console.ReadKey(true);
if (cki.Key == ConsoleKey.Enter) break;
else if (cki.Key == ConsoleKey.Escape)
{
password.Dispose();
return null;
}
else if (cki.Key == ConsoleKey.Backspace)
{
if (password.Length != 0)
password.RemoveAt(password.Length - 1);
}
else password.AppendChar(cki.KeyChar);
}
return password;
}
</pre>
</div>
</div>
</div>
</div>
<div class="ArticleNormalPara">在&#8220;使用 .NET Framework 2.0 进行加密管理&#8221;（可从 <a href="http://msdn2.microsoft.com/aa480470.aspx">msdn.microsoft.com/library/en-us/dnnetsec/html/credmgmt.asp</a> 获得）一文中，Kenny Kerr 谈到了将常见 Windows 凭据对话框的结果转换为 SecureString 的代码。不管您以何种方式获得 SecureString，它都可以随后被传递到 X509Certificate2 构造函数，以加载 .pfx 文件，如下所示：
<div class="" id="ctl00_ContentPlaceHolder1_ctl09_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl09');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl09" space="preserve">X509Certificate2 cert2 = new X509Certificate2("alice.pfx", password);
</pre>
</div>
</div>
<div class="ArticleNormalPara">要访问 Windows 证书存储区，请使用 X509Store 类。在其构造函数中，您要提供存储区位置（当前用户或计算机）和存储区名称。可以使用字符串或 StoreName 枚举来指定要打开的容器。注意，内部名称并不总是与 MMC 管理单元中找到的名称匹配。Personal 容器映射到名称 My，而 Other People 则变为 AddressBook。</div>
<div class="ArticleNormalPara">获得有效的 X509Store 实例后，就可以搜索、检索、删除和添加证书。除非在部署情况下，否则使用最为频繁的恐怕要数搜索功能。您可以按各种条件搜索证书，其中包括使用者名称、序列号、指纹、颁发者和有效期。如果以编程方式从存储区检索应用程序中的证书，则应当使用唯一的属性，例如接收者密钥标识符。指纹虽然也是唯一的，但要记住，它是证书的一个 SHA-1 哈希值，在诸如续订证书时会发生改变。<strong>图 3</strong> 中的代码显示了一种搜索证书的常规方法。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109038">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109038_h"><img id="ctl00_ContentPlaceHolder1_cpe109038_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;3&nbsp;搜索证书 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109038_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl13_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl13');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl13" space="preserve">static void Main(string[] args)
{
// search for the subject key id
X509Certificate2 cert = FindCertificate(
StoreLocation.CurrentUser, StoreName.My,
X509FindType.FindBySubjectKeyIdentifier,
"21f2bf447298e83056a69eb02ebe9085ed97f10a");
}
static X509Certificate2 FindCertificate(
StoreLocation location, StoreName name,
X509FindType findType, string findValue)
{
X509Store store = new X509Store(name, location);
try
{
// create and open store for read-only access
store.Open(OpenFlags.ReadOnly);
// search store
X509Certificate2Collection col = store.Certificates.Find(
findType, findValue, true);
// return first certificate found
return col[0];
}
// always close the store
finally { store.Close(); }
}
</pre>
</div>
</div>
</div>
</div>
<div class="ArticleNormalPara">在获得 X509 Certificate2 的一个实例后，可以检查证书的各个属性（如使用者名称、到期日期、颁发者和友好名称）。HasPrivateKey 属性会告知您是否存在关联私钥。PrivateKey 和 PublicKey 属性将对应密钥作为一个 RSACryptoServiceProvider 实例返回。</div>
<div class="ArticleNormalPara">要导入证书，请对 X509Store 实例调用 Add 方法。当存储区的构造函数中不存在您所指定的存储区名称时，就会创建一个新容器。以下说明了如何将名为 alice.cer 的文件中的一个证书导入到名为 Test 的新容器中：
<div class="" id="ctl00_ContentPlaceHolder1_ctl14_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl14');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl14" space="preserve">static void ImportCert()
{
X509Certificate2 cert = new X509Certificate2("alice.cer");
X509Store store = new X509Store("Test", StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
}
finally { store.Close(); }
}
</pre>
</div>
</div>
<br />
<div class="ArticleTypeTitle" id="S5">显示证书详细信息和证书选择器</div>
<div class="ArticleNormalPara">Windows 提供了两个标准对话框对证书进行操作：其中一个对话框用于显示证书的详细信息（各个属性和证书路径），另一个则供用户从列表中选择证书。您可以使用 X509Certificate2UI 类的两个静态方法访问这两个对话框：SelectFromCollection 和 DisplayCertificate。</div>
<div class="ArticleNormalPara">要显示证书列表，必须填充 X509Certificate2Collection 并将其传递给 SelectFromCollection。让用户从存储区内的个人证书之一进行选择是很常见的。为此，只需传入一个已打开的 X509Store 的 Certificates 属性即可。您还可以控制对话框标题、消息以及是否允许多个选择。DisplayCertificate 方法显示的对话框与在 Windows 资源管理器中双击 .cer 文件时看到的对话框相同。<strong>图 4</strong> 显示了选择证书所用的对话框，<strong>图 5</strong> 提供相应的代码。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109039">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109039_h"><img id="ctl00_ContentPlaceHolder1_cpe109039_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;5&nbsp;用于选择证书的代码 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109039_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl18_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl18');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl18" space="preserve">private static X509Certificate2 PickCertificate(
StoreLocation location, StoreName name)
{
X509Store store = new X509Store(name, location);
try
{
store.Open(OpenFlags.ReadOnly);
// pick a certificate from the store
X509Certificate2 cert =
X509Certificate2UI.SelectFromCollection(
store.Certificates, "Caption",
"Message", X509SelectionFlag.SingleSelection)[0];
// show certificate details dialog
X509Certificate2UI.DisplayCertificate(cert);
return cert;
}
finally { store.Close(); }
}
</pre>
</div>
</div>
</div>
</div>
<div class="ArticleImageSpacer"><img onmouseover="this.style.cursor='pointer';" onclick="var large='http://i.msdn.microsoft.com/cc163454.certificatesfig04_L.gif'; var small='http://i.msdn.microsoft.com/cc163454.certificatesfig04.gif'; var current=this.src;  if (current.indexOf(large) > 0) this.src=small; if (current.indexOf(small) > 0)this.src=large;" alt="" src="http://i.msdn.microsoft.com/cc163454.certificatesfig04.gif">
<div class="ArticleImageCaptionText">图 4<strong>&nbsp;用于选择证书的对话框&nbsp;</strong>(单击该图像获得较大视图)</div>
</div>
<br />
<div class="ArticleTypeTitle" id="S6">验证证书</div>
<div class="ArticleNormalPara">验证证书时需要考虑几个条件，尤其是颁发方（通常仅信任可信 CA 列表中的 CA 所颁发的证书）及其当前有效性（证书可能会失效，例如当过期或者被颁发证书的 CA 吊销时）。X509Chain 类可以用来检查这些不同属性。使用该类，您可以为有效性检查指定策略，例如，可以要求一个受信任根 CA 或指定是否进行联机检查或检查本地吊销列表。如果需要对用于数据签名的证书进行检查，则在计算签名时检查证书是否有效就变得很重要；为此，X509Chain 允许更改验证时间。</div>
<div class="ArticleNormalPara">构造策略后，可以调用 Build 方法来获取有关 ChainStatus 属性验证结果的信息。如果出现多个验证错误，您可以循环访问 ChainElement 集合以获取更多详细信息。<strong>图 6</strong> 显示了如何根据脱机和联机吊销列表对证书及其颁发者执行严格的验证。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109040">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109040_h"><img id="ctl00_ContentPlaceHolder1_cpe109040_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;6&nbsp;严格的证书验证 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109040_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl23_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl23');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl23" space="preserve">static void ValidateCert(X509Certificate2 cert)
{
X509Chain chain = new X509Chain();
// check entire chain for revocation
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
// check online and offline revocation lists
chain.ChainPolicy.RevocationMode =
X509RevocationMode.Online | X509RevocationMode.Offline;
// timeout for online revocation list
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 30);
// no exceptions, check all properties
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
// modify time of verification
//chain.ChainPolicy.VerificationTime = new DateTime(1999, 1, 1);
chain.Build(cert);
if (chain.ChainStatus.Length != 0)
Console.WriteLine(chain.ChainStatus[0].Status);
}
</pre>
</div>
</div>
</div>
</div>
<br />
<div class="ArticleTypeTitle" id="S7">SSL 支持</div>
<div class="ArticleNormalPara">SSL 身份验证协议依赖于证书。.NET Framework 中对 SSL 的支持包含两个部分。HTTP 上的 SSL 这种特殊情况（但使用最为广泛）由 HttpWebRequest 类（它最终还可用于 Web 服务客户端代理）实现。要启用 SSL，除了要指定一个使用 Https: 协议的 URL 外，不必执行任何特殊操作。</div>
<div class="ArticleNormalPara">当连接到一个受 SSL 保护的终结点时，会在客户端上对服务器证书进行验证。如果验证失败，连接会根据默认设置立即关闭。您可以回调一个名为 ServicePointManager 的类来重写该行为。每当 HTTP 客户端的堆栈进行证书验证时，都会首先检查是否可以回调；如果可以，则执行您的代码。要挂接该回调，您必须提供类型 RemoteCertificateValidationCallback 的一个委托：
<div class="" id="ctl00_ContentPlaceHolder1_ctl24_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl24');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl24" space="preserve">// override default certificate policy
// (for example, for testing purposes)
ServicePointManager.ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback(VerifyServerCertificate);
</pre>
</div>
</div>
<div class="ArticleNormalPara">在回调中，您会获得服务器证书、一个错误代码和一个传入的链对象，然后可以执行自己的检查并返回 true 或 false。如果出现诸如证书在开发或测试期间就已过期的情况，那么关闭其中某项检查是有好处的。另一方面，这样做还可以执行比默认更为严格的验证策略。<strong>图 7</strong> 提供了一个验证回调的示例。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109041">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109041_h"><img id="ctl00_ContentPlaceHolder1_cpe109041_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;7&nbsp;验证回调 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109041_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl28_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl28');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl28" space="preserve">private bool VerifyServerCertificate(
object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None) return true;
foreach (X509ChainStatus s in chain.ChainStatus)
{
// allows expired certificates
if (string.Equals(s.Status.ToString(), "NotTimeValid",
StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
</pre>
</div>
</div>
</div>
</div>
<div class="ArticleNormalPara">SSL 还支持使用证书对客户端进行身份验证。如果您要访问的网站或服务要求提供客户端证书，那么 Web 服务客户端代理和 HttpWebRequest 都可提供 X509Certicate 类型的 ClientCertificates 属性：
<div class="" id="ctl00_ContentPlaceHolder1_ctl29_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl29');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl29" space="preserve">  proxy.Url =
"https://server/app/service.asmx";
proxy.ClientCertificates.Add(
PickCertificate(...));
</pre>
</div>
</div>
<div class="ArticleNormalPara">此外，.NET Framework 2.0 还引入了一个名为 SslStream 的新类。该类允许您在任何流的顶部设置 SSL 层，而不仅限于 HTTP，从而可以对基于套接字的自定义协议启用 SSL。SslStream 将标准 .NET 证书支持应用于各个方面，例如，使用我所讨论的验证回调机制：
<div class="" id="ctl00_ContentPlaceHolder1_ctl30_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl30');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl30" space="preserve">public SslStream(Stream innerStream, bool leaveInnerStreamOpen,
RemoteCertificateValidationCallback ValidationCallback) {...}
</pre>
</div>
</div>
<div class="ArticleNormalPara">要使用 SslStream 启动 SSL 身份验证，请将 X509Certificate 传递给其 AuthenticateAsServer 方法：
<div class="" id="ctl00_ContentPlaceHolder1_ctl31_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl31');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl31" space="preserve">ssl.AuthenticateAsServer(PickCertificate(...));
</pre>
</div>
</div>
<br />
<div class="ArticleTypeTitle" id="S8">Web 服务安全性</div>
<div class="ArticleNormalPara">WS 安全性标准使用证书来指定客户端和服务器的身份验证并确保通信安全。诸如 .NET Framework 的 Web 服务增强 (WSE) 的各种工具包以及诸如 Windows Communication Foundation 的各项技术都对此提供了完全的支持。同样，最终还是要通过代码或配置来提供证书。以下代码段说明了如何使用 WSE3 向 Web 服务代理添加一个客户端证书：
<div class="" id="ctl00_ContentPlaceHolder1_ctl32_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl32');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl32" space="preserve">X509SecurityToken token = new X509SecurityToken(PickCertificate(...));
proxy.RequestSoapContext.Security.Tokens.Add(token);
</pre>
</div>
</div>
<div class="ArticleNormalPara">对于 Windows Communication Foundation，通常要引用配置文件中的证书存储区（参见<strong>图 8</strong>）。如您所见，所有配置属性都直接映射到在前面代码中使用的枚举。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109042">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109042_h"><img id="ctl00_ContentPlaceHolder1_cpe109042_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;8&nbsp;在 WCF 中提供证书引用 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109042_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl36_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl36');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl36" space="preserve">&lt;system.serviceModel&gt;
&lt;behaviors&gt;
&lt;serviceBehaviors&gt;
&lt;behavior name="ServiceBehavior"&gt;
&lt;serviceCredentials&gt;
&lt;serviceCertificate storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectKeyIdentifier"
findValue="1a7b..." /&gt;
&lt;/serviceCredentials&gt;
&lt;/behavior&gt;
&lt;/serviceBehaviors&gt;
&lt;/behaviors&gt;
&lt;/system.serviceModel&gt;
</pre>
</div>
</div>
</div>
</div>
<br />
<div class="ArticleTypeTitle" id="S9">安全策略和代码签名</div>
<div class="ArticleNormalPara">证书还应用于 Authenticode<span class="superscript">&#174;</span> 代码签名。通过对二进制文件进行签名，您可以添加有关发布者的信息，并确保签名完成后该签名文件能得到可靠验证。.NET Framework SDK 中的 signtool.exe 工具可用于对 .exe 文件和 .dll 文件进行签名。签名后，使用 Windows 资源管理器中的属性对话框验证签名并查看证书。注意，如果要同时使用 Authenticode 签名和强名称签名，需要首先应用强名称签名。此外，在加载时，Authenticode 签名的程序集可能会出现延迟。如果被签名位置为可执行文件的入口点，则延迟会导致应用程序的启动时间延长。</div>
<div class="ArticleNormalPara">已签名文件还可用于安全策略。使用软件限制策略，您可以根据签名或缺少签名来限制非托管可执行文件的执行（请参阅 <a href="http://microsoft.com/technet/prodtechnol/winxppro/maintain/rstrplcy.mspx">microsoft.com/technet/prodtechnol/winxppro/maintain/rstrplcy.mspx</a>）。而且 .NET Framework 代码访问安全 (CAS) 策略可以根据发行者证书来支持代码组。</div>
<div class="ArticleNormalPara">要创建一个 CAS 策略，请根据发行者成员条件使用 mscorcfg.msc 创建一个新的代码组。然后将一个权限集分配给由该发行者签名的所有应用程序（参见<strong>图 9</strong>）。</div>
<div class="ArticleImageSpacer"><img onmouseover="this.style.cursor='pointer';" onclick="var large='http://i.msdn.microsoft.com/cc163454.certificatesfig09_L.gif'; var small='http://i.msdn.microsoft.com/cc163454.certificatesfig09.gif'; var current=this.src;  if (current.indexOf(large) > 0) this.src=small; if (current.indexOf(small) > 0)this.src=large;" alt="" src="http://i.msdn.microsoft.com/cc163454.certificatesfig09.gif">
<div class="ArticleImageCaptionText">图 9<strong>&nbsp;将权限分配给发行者&nbsp;</strong>(单击该图像获得较大视图)</div>
</div>
<br />
<div class="ArticleTypeTitle" id="S10">ClickOnce 清单</div>
<div class="ArticleNormalPara">另一种将证书用于发行者信息的技术是 ClickOnce。在发布一个 ClickOnce 应用程序时，您必须对部署和应用程序清单进行签名。这会再次将发行者信息添加到应用程序，并确保清单中的敏感信息只有在签名失效的情况下才能被修改（如安全策略和应用程序依赖项）。在安装过程中，ClickOnce 使客户端能够使用发行者信息，以便客户可以对应用程序的可信性做出明智的决策。根据证书及其验证结果的不同，ClickOnce 安装程序还使用不同的可视化提示。<strong>图 10</strong> 显示了 Visual Studio<span class="superscript">&#174;</span> 清单签名对话框。</div>
<div class="ArticleImageSpacer"><img onmouseover="this.style.cursor='pointer';" onclick="var large='http://i.msdn.microsoft.com/cc163454.certificatesfig10_L.gif'; var small='http://i.msdn.microsoft.com/cc163454.certificatesfig10.gif'; var current=this.src;  if (current.indexOf(large) > 0) this.src=small; if (current.indexOf(small) > 0)this.src=large;" alt="" src="http://i.msdn.microsoft.com/cc163454.certificatesfig10.gif">
<div class="ArticleImageCaptionText">图 10<strong>&nbsp;Visutal Studio 清单签名对话框&nbsp;</strong>(单击该图像获得较大视图)</div>
</div>
<br />
<div class="ArticleTypeTitle" id="S11">对数据进行签名和加密</div>
<div class="ArticleNormalPara">到目前为止，我主要介绍了与证书有关的基础 API 以及其他技术如何使用这些 API。现在我想与大家讨论一下加密操作（如使用证书对数据加密和签名）和如何实现 .NET Framework 2.0 中新发现的 PKCS #7。</div>
<div class="ArticleNormalPara">数据的保护始终分为两个步骤。首先，对数据进行签名以防止其被篡改。然后，对数据进行加密以防止其被泄漏。但是，在使用 PKCS #7 类执行任何加密操作之前，都必须先将数据包装在一个 ContentInfo 对象中，表示为一个 CMS 数据结构。数据将从这里转换为已签名或加密的数据，分别由 SignedCms 和 EnvelopedCms 类来表示。</div>
<div class="ArticleNormalPara">从技术上讲，数字签名是对随后使用私钥加密的数据的哈希。这意味着您需要一个含有关联私钥或 .pfx 文件的证书。您可以根据这种证书创建一个代表数据签名者的 CmsSigner 对象。接着 SignedCms 类会对签名进行计算并输出一个符合 PKCS #7 和 CMS 的字节数组。<strong>图 11</strong> 显示了对应的代码。已编码的字节数组包含了您的数据、签名和用于对数据签名的证书。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109043">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109043_h"><img id="ctl00_ContentPlaceHolder1_cpe109043_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;11&nbsp;输出符合 CMS 的字节数组 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109043_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl42_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl42');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl42" space="preserve">byte[] Sign(byte[] data, X509Certificate2 signingCert)
{
// create ContentInfo
ContentInfo content = new ContentInfo(data);
// SignedCms represents signed data
SignedCms signedMessage = new SignedCms(content);
// create a signer
CmsSigner signer = new CmsSigner(signingCert);
// sign the data
signedMessage.ComputeSignature(signer);
// create PKCS #7 byte array
byte[] signedBytes = signedMessage.Encode();
// return signed data
return signedBytes;
}
</pre>
</div>
</div>
</div>
</div>
<div class="ArticleNormalPara">如果您要对大量数据签名，这样做可能没有什么；但如果要签名的数据量很小，则会增加一些开销。例如，使用 2KB 公钥对一个 10 字节数组进行签名会产生一个大约 2,400 字节的数组。如果您打算将已签名数据存储在（比如说）数据库中，那么请牢记这一点。另一种方法是使用所谓的分离签名。这种方法使您能够从签名中删除数据并单独进行存储。例如，您可以先将多个小数据段加以组合，然后统一对其进行签名。要创建一个分离签名，必须向 SignedCms 构造函数再传递一个 true 值，如<strong>图 12</strong> 所示。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109044">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109044_h"><img id="ctl00_ContentPlaceHolder1_cpe109044_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;12&nbsp;创建分离签名 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109044_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl46_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl46');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl46" space="preserve">byte[] SignDetached(byte[] data, X509Certificate2 signingCert)
{
// create ContentInfo
ContentInfo content = new ContentInfo(data);
// pass true to the constructor to indicate
// we want to sign detached
SignedCms signedMessage = new SignedCms(content, true);
// these steps are the same
CmsSigner signer = new CmsSigner(signingCert);
signedMessage.ComputeSignature(signer);
byte[] signedBytes = signedMessage.Encode();
// return only the signature (not the data)
return signedBytes;
}
</pre>
</div>
</div>
</div>
</div>
<div class="ArticleNormalPara">对数据进行签名后，即可对其加密。您需要接收者的公钥才能对数据进行解密。通常这些公钥可以从 Other People 存储区获得，但如果不希望使用证书存储区，也可以从 .cer 文件获取公钥。这样一来，所有繁重工作就交给 EnvelopedCms 类来执行。您需要在 CmsRecipientCollection 中指定一个用于加密的公钥并将其传递到 Encrypt 方法中。与 SignedCms 一样，Encode 方法会在此处创建符合 PKCS #7 和 CMS 的字节数组（参见<strong>图 13</strong>）。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109045">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109045_h"><img id="ctl00_ContentPlaceHolder1_cpe109045_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;13&nbsp;Encode 方法 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109045_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl50_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl50');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl50" space="preserve">byte[] Encrypt(byte[] data, X509Certificate2 encryptingCert)
{
// create ContentInfo
ContentInfo plainContent = new ContentInfo(data);
// EnvelopedCms represents encrypted data
EnvelopedCms encryptedData = new EnvelopedCms(plainContent);
// add a recipient
CmsRecipient recipient = new CmsRecipient(encryptingCert);
// encrypt data with public key of recipient
encryptedData.Encrypt(recipient);
// create PKCS #7 byte array
byte[] encryptedBytes = encryptedMessage.Encode();
// return encrypted data
return encryptedBytes;
}
</pre>
</div>
</div>
</div>
</div>
<div class="ArticleNormalPara">EnvelopedCms 在内部生成一个随机会话密钥，数据借助该密钥被对称加密。随后再使用每个接收者的公钥对该会话密钥进行加密。这样一来，您就无需为每个收件人单独保留一份数据的加密版本。另外数据中还嵌入了一些额外的信息，使接收者能够从自己的证书存储区中找到匹配的私钥来解密数据。</div>
<br />
<div class="ArticleTypeTitle" id="S12">解密数据和验证签名</div>
<div class="ArticleNormalPara">接收端的整个解密过程是与加密过程是截然相反的。也就是说，首先要将数据解密，然后再验证签名和签名证书。在代码中，您必须首先调用 SignedCms 和 EnvelopedCms 类的 Decode 方法，将 CMS 字节数组反序列化为对象表示形式。然后再分别调用 Decrypt 和 CheckSignature。</div>
<div class="ArticleNormalPara">该过程会查看已加密的数据包，以判断是否可以通过在证书存储区中搜索对应的私钥来解密会话密钥。随后再使用已解密的会话密钥对实际数据进行解密。您也可以提供一个解密期间要加以考虑的额外证书的列表，以防私钥并未存储在证书存储区：
<div class="" id="ctl00_ContentPlaceHolder1_ctl51_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl51');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl51" space="preserve">static byte[] Decrypt(byte[] data)
{
// create EnvelopedCms
EnvelopedCms encryptedMessage = new EnvelopedCms();
// deserialize PKCS#7 byte array
encryptedMessage.Decode(data);
// decryt data
encryptedMessage.Decrypt();
// return plain text data
return encryptedMessage.ContentInfo.Content;
}
</pre>
</div>
</div>
<div class="ArticleNormalPara">验证数据的过程分为两步。首先，确保签名是有效的，也就是说数据是未被篡改的。然后检查签名证书。使用 SignedCms 类的 CheckSignature 方法可同时执行这两步操作在这种情况下，证书会比照默认的系统策略被验证。如果您希望对该过程进行更大程度的控制，可以使用 X509Chain 对象和代码（如<strong>图 6</strong> 所示）亲自进行检查。<strong>图 14</strong> 显示了用于检查和删除签名的代码，而<strong>图 15</strong> 提供了用于验证分离签名的代码。</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109046">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109046_h"><img id="ctl00_ContentPlaceHolder1_cpe109046_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;15&nbsp;分离签名验证 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109046_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl55_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl55');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl55" space="preserve">static bool VerifyDetached(byte[] data, byte[] signature)
{
ContentInfo content = new ContentInfo(data);
// pass true for detached
SignedCms signedMessage = new SignedCms(content, true);
// deserialize signature
signedMessage.Decode(signature);
try
{
// check if signature matches data
// the certificate is also checked
signedMessage.CheckSignature(false);
return true;
}
catch { return false; }
}
</pre>
</div>
</div>
</div>
</div>
<div class="MTPS_CollapsibleRegion" id="ctl00_ContentPlaceHolder1_cpe109047">
<div class="CollapseRegionLink" id="ctl00_ContentPlaceHolder1_cpe109047_h"><img id="ctl00_ContentPlaceHolder1_cpe109047_i" style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-right-width: 0px" src="http://i.msdn.microsoft.com/Platform/Controls/CollapsibleArea/resources/plus.gif"  alt="" />&nbsp;Figure&nbsp;14&nbsp;验证和删除签名 </div>
<div class="MTPS_CollapsibleSection" id="ctl00_ContentPlaceHolder1_cpe109047_c" style="display: none; overflow: hidden; width: auto; height: 0px" olddisplay="block">
<div class="MTPS_CollapsibleSection" id="" style="border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none">
<div class="" id="ctl00_ContentPlaceHolder1_ctl59_">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/cuihongyu3503319/admin/javascript:CopyCode('ctl00_ContentPlaceHolder1_ctl59');"><img height="9" src="http://i.msdn.microsoft.com/Platform/Controls/CodeSnippet/resources/copy_off.gif" align="center" border="0"  alt="" /> 复制代码</a></div>
</div>
<pre class="libCScode" id="ctl00_ContentPlaceHolder1_ctl59" space="preserve">byte[] VerifyAndRemoveSignature(byte[] data)
{
// create SignedCms
SignedCms signedMessage = new SignedCms();
// deserialize PKCS #7 byte array
signedMessage.Decode(data);
// check signature
// false checks signature and certificate
// true only checks signature
signedMessage.CheckSignature(false);
// access signature certificates (if needed)
foreach (SignerInfo signer in signedMessage.SignerInfos)
{
Console.WriteLine("Subject: {0}",
signer.Certificate.Subject);
}
// return plain data without signature
return signedMessage.ContentInfo.Content;
}
</pre>
</div>
</div>
</div>
</div>
<br />
<div class="ArticleTypeTitle" id="S13">综述</div>
<div class="ArticleNormalPara">在使用安全策略或通信协议时，您会发现各种情况下都需要用到证书。本文介绍了用于检索和搜索证书的基础 API 以及如何利用这些 API 进行加密和数字签名。此外，我还为大家提供了一些更高级的应用程序服务的示例，这些服务要求您对 Windows 证书存储区以及公钥和私钥之间的关系有所了解。</div>
<div class="ArticleNormalPara">本文的源代码可以从<em>《MSDN<span class="superscript">&#174;</span> 杂志》<em>网站下载，其中包括一个很小的支持对文件签名和加密的 Windows 窗体应用程序。该程序使用了本文所讨论的多种方法，如从不同的存储区选择证书以及使用加密和签名来保护/验证数据。</div>
<br />
<div class="ContentSeparator">
<div class="AuthorBio"><strong>Dominick Baier</strong>是德国的一位独立安全咨询师。他帮助各家公司处理安全设计和体系结构、内容开发、渗透测试和代码审核等方面的问题。他还是 <a href="http://www.develop.com/">DevelopMentor</a> 的安全课程负责人和开发人员安全 MVP，同时也是《Developing More-Secure Microsoft ASP.NET 2.0 Applications》（Microsoft Press，2006）一书的作者。他在 <a href="http://www.leastprivilege.com/">http://www.leastprivilege.com/</a> 开设了博客。</div>
</em></em></em></div>
</div>
</div>
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1251373.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41316/" target="_blank">[新闻]腾讯CEO马化腾:中国互联网业准备再过冬</a>]]></description></item><item><title>asp.net 使用timer 定时执行任务</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/24/1250735.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Thu, 24 Jul 2008 09:08:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/24/1250735.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1250735.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/24/1250735.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1250735.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1250735.html</trackback:ping><description><![CDATA[protected void Application_Start(Object sender, EventArgs e) <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;System.Timers.Timer myTimer=new System.Timers.Timer(10000);&nbsp;<br />
&nbsp;&nbsp;&nbsp;myTimer.Elapsed+=new System.Timers.ElapsedEventHandler(examlpe); <br />
&nbsp;&nbsp;&nbsp;myTimer.AutoReset = true ;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Application.Lock(); <br />
&nbsp;&nbsp;&nbsp;Application["a"]= DateTime.Now.ToString(); <br />
&nbsp;&nbsp;&nbsp;Application.UnLock(); <br />
&nbsp;&nbsp;&nbsp;myTimer.Enabled = true ; <br />
&nbsp;&nbsp;} <br />
&nbsp;&nbsp;private void examlpe(object sender,&nbsp; ElapsedEventArgs e) <br />
&nbsp;&nbsp;{&nbsp;<br />
&nbsp;&nbsp;&nbsp;Application.Lock(); <br />
&nbsp;&nbsp;&nbsp;Application["a"]= DateTime.Now.ToString(); <br />
&nbsp;&nbsp;&nbsp;Application.UnLock(); <br />
&nbsp;&nbsp;}<br />
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1250735.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41315/" target="_blank">[新闻]F8 Keynote Speech[多图]</a>]]></description></item><item><title>asp.net一个onclick的全过程(简单写一下)</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/24/1250561.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Thu, 24 Jul 2008 07:13:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/24/1250561.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1250561.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/24/1250561.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1250561.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1250561.html</trackback:ping><description><![CDATA[<p><font face="Verdana">1.ie页面初始化的时候把每个控件初始化位置（热区）<br />
2.点击鼠标<br />
3.如果点击时鼠标位置在IE的button位置 那么IE认为这个button被点击(调系统API了)<br />
4.触发客户端onclick事件并记录点击信息到viewstate等<br />
5.submit到服务器</font></p>
<p><font face="Verdana">...........................http协议，IIS服务器，映射</font><font face="Verdana"><br />
6.request.form得到值，判断button是否被点击<br />
7.如果被点击 执行button.click()方法(这个方法应该是被封装了)<br />
8.button.click()方法里面定义委托<br />
9.然后委托给页面方法去做<br />
10.ok!这就是一个完整的请求</font></p>
<p>其它控件事件应该和这个类似，可能有不对的地方，请指出</p>
<p>还有，其中点击发生的源头只有一个那就是客户端的人点了一下鼠标</p>
<p>&nbsp;</p>
<p><clk>asp.net中控件的生命周期以控件的事件原理！对于标准的Form控件要实现IPostBackDataHandler和IPostBackEventHandler.这两个都是在PostBack才会引发的动作。当我们第一次请求页面的时候是不会做这两个动作的。但是当我们在页面上执行Button的时候，就会Submit &nbsp; Form.(asp.net中Web &nbsp; Button默认为Submit)。这个时候在服务器端通过Request.Form就会知道客户端的哪一个Button提交的，如果该Button有事件的话就会执行事件！&nbsp;&nbsp;</p>
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1250561.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41315/" target="_blank">[新闻]F8 Keynote Speech[多图]</a>]]></description></item><item><title>HTTP消息头</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/24/1250248.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Thu, 24 Jul 2008 02:14:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/24/1250248.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1250248.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/24/1250248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1250248.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1250248.html</trackback:ping><description><![CDATA[<div>但凡搞WEB开发的人都离不开HTTP（超文本传输协议），而要了解HTTP，除了HTML本身以外，还有一部分不可忽视的就是HTTP消息头。<br />
做过Socket编程的人都知道，当我们设计一个通信协议时，&#8220;消息头/消息体&#8221;的分割方式是很常用的，消息头告诉对方这个消息是干什么的，消息体告诉对方怎么干。HTTP传输的消息也是这样规定的，每一个HTTP包都分为HTTP头和HTTP体两部分，后者是可选的，而前者是必须的。每当我们打开一个网页，在上面点击右键，选择&#8220;查看源文件&#8221;，这时看到的HTML代码就是HTTP的消息体，那么消息头又在哪呢？IE浏览器不让我们看到这部分，但我们可以通过截取数据包等方法看到它。<br />
下面就来看一个简单的例子：<br />
首先制作一个非常简单的网页，它的内容只有一行：<br />
<font face="Verdana, Geneva, Arial, Sans-serif" color="#33cccc"><font color="#003366">&lt;html&gt;&lt;body&gt;hello world&lt;/body&gt;&lt;/html&gt;</font><br />
</font>把它放到WEB服务器上，比如IIS，然后用IE浏览器请求这个页面（<a href="http://localhost:8080/simple.htm"><font color="#4388d2">http://localhost:8080/simple.htm</font></a>），当我们请求这个页面时，浏览器实际做了以下四项工作：<br />
1 解析我们输入的地址，从中分解出协议名、主机名、端口、对象路径等部分，对于我们的这个地址，解析得到的结果如下：<br />
协议名：http<br />
主机名：localhost<br />
端口：8080<br />
对象路径：/simple.htm<br />
2 把以上部分结合本机自己的信息，封装成一个HTTP请求数据包<br />
3 使用TCP协议连接到主机的指定端口（localhost, 8080），并发送已封装好的数据包<br />
4 等待服务器返回数据，并解析返回数据，最后显示出来<br />
由截取到的数据包我们不难发现浏览器生成的HTTP数据包的内容如下：<br />
<font color="#003366">GET /simple.htm HTTP/1.1&lt;CR&gt;<br />
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*&lt;CR&gt;<br />
Accept-Language: zh-cn&lt;CR&gt;<br />
Accept-Encoding: gzip, deflate&lt;CR&gt;<br />
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)&lt;CR&gt;<br />
Host: localhost:8080&lt;CR&gt;<br />
Connection: Keep-Alive&lt;CR&gt;<br />
&lt;CR&gt;<br />
</font>为了显示清楚我把所有的回车的地方都加上了&#8220;&lt;CR&gt;&#8221;，注意最后还有一个空行加一个回车，这个空行正是HTTP规定的消息头和消息体的分界线，第一个空行以下的内容就是消息体，这个请求数据包是没有消息体的。<br />
消息的第一行&#8220;GET&#8221;表示我们所使用的HTTP动作，其他可能的还有&#8220;POST&#8221;等，GET的消息没有消息体，而POST消息是有消息体的，消息体的内容就是要POST的数据。后面/simple.htm就是我们要请求的对象，之后HTTP1.1表示使用的是HTTP1.1协议。<br />
第二行表示我们所用的浏览器能接受的Content-type，三四两行则是语言和编码信息，第五行显示出本机的相关系信息，包括浏览器类型、操作系统信息等，很多网站可以显示出你所使用的浏览器和操作系统版本，就是因为可以从这里获取到这些信息。<br />
第六行表示我们所请求的主机和端口，第七行表示使用Keep-Alive方式，即数据传递完并不立即关闭连接。<br />
服务器接收到这样的数据包以后会根据其内容做相应的处理，例如查找有没有&#8220;/simple.htm&#8221;这个对象，如果有，根据服务器的设置来决定如何处理，如果是HTM，则不需要什么复杂的处理，直接返回其内容即可。但在直接返回之前，还需要加上HTTP消息头。<br />
服务器发回的完整HTTP消息如下：<br />
<font face="Verdana, Geneva, Arial, Sans-serif" color="#003366">HTTP/1.1 200 OK&lt;CR&gt;<br />
Server: Microsoft-IIS/5.1&lt;CR&gt;<br />
X-Powered-By: ASP.NET&lt;CR&gt;<br />
Date: Fri, 03 Mar 2006 06:34:03 GMT&lt;CR&gt;<br />
Content-Type: text/html&lt;CR&gt;<br />
Accept-Ranges: bytes&lt;CR&gt;<br />
Last-Modified: Fri, 03 Mar 2006 06:33:18 GMT&lt;CR&gt;<br />
ETag: "5ca4f75b8c3ec61:9ee"&lt;CR&gt;<br />
Content-Length: 37&lt;CR&gt;<br />
&lt;CR&gt;<br />
&lt;html&gt;&lt;body&gt;hello world&lt;/body&gt;&lt;/html&gt;<br />
</font>同样，我用&#8220;&lt;CR&gt;&#8221;来表示回车。可以看到，这个消息也是用空行切分成消息头和消息体两部分，消息体的部分正是我们前面写好的HTML代码。<br />
消息头第一行&#8220;HTTP/1.1&#8221;也是表示所使用的协议，后面的&#8220;200 OK&#8221;是HTTP返回代码，200就表示操作成功，还有其他常见的如404表示对象未找到，500表示服务器错误，403表示不能浏览目录等等。<br />
第二行表示这个服务器使用的WEB服务器软件，这里是IIS 5.1。第三行是ASP.Net的一个附加提示，没什么实际用处。第四行是处理此请求的时间。第五行就是所返回的消息的content-type，浏览器会根据它来决定如何处理消息体里面的内容，例如这里是text/html，那么浏览器就会启用HTML解析器来处理它，如果是image/jpeg，那么就会使用JPEG的解码器来处理。<br />
消息头最后一行&#8220;Content-Length&#8221;表示消息体的长度，从空行以后的内容算起，以字节为单位，浏览器接收到它所指定的字节数的内容以后就会认为这个消息已经被完整接收了。</div>
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1250248.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41315/" target="_blank">[新闻]F8 Keynote Speech[多图]</a>]]></description></item><item><title>VSS出项错误"Could not find the Visual SourceSafe Internet Web Service connection..."</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/22/1248938.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Tue, 22 Jul 2008 10:26:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/22/1248938.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1248938.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/22/1248938.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1248938.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1248938.html</trackback:ping><description><![CDATA[<strong>Solution:</strong><br />
打开vs2005—&gt;工具—&gt;选项—&gt;源代码管理—&gt;当前源代码管理插件改为：Microsoft Visual SourceSafe 。
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1248938.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41314/" target="_blank">[新闻]奥运核心资源被分食 搜狐央视网谁忽悠谁？</a>]]></description></item><item><title>Eval和Bind的区别(不是其他人说的那个，突然发现的)</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/03/1234916.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Thu, 03 Jul 2008 08:55:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/03/1234916.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1234916.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/03/1234916.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1234916.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1234916.html</trackback:ping><description><![CDATA[<font face="Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
IList&lt;A&gt; As =&nbsp;GetAs();<br />
GridViewList.DataSource = As;<br />
GridViewList.DataBind();<br />
</font>
<p><font face="Verdana">其中<span style="color: red">B</span>是自定义的一个类是<span style="color: red">A</span>类中的一个属性，Name是<span style="color: red">B</span>类中的一个属性绑定GridViewList上的As是<span style="color: red">A</span>类的一个泛型集合<br />
下面的绑定<span style="color: #0000ff">Eval</span>可以正确现实，但是换成<font style="color: #0000ff" face="Verdana">Bind</font>报错，为什么不清楚<br />
&lt;asp:TemplateField HeaderText="Page Title"&gt;<br />
&lt;ItemTemplate&gt;<br />
&lt;asp:Label ID="Label1" runat="server" Text='&lt;%# <span style="color: #0000ff">Eval</span>("<span style="color: red">B</span>.Name") %&gt;'&gt;&lt;/asp:Label&gt;<br />
&lt;/ItemTemplate&gt;<br />
&lt;/asp:TemplateField&gt;<br />
<br />
</p>
<p><font face="Verdana">&lt;asp:TemplateField HeaderText="Page Title"&gt;<br />
&lt;ItemTemplate&gt;<br />
&lt;asp:Label ID="Label1" runat="server" Text='&lt;%# <font style="color: #0000ff" face="Verdana">Bind</font>("<span style="color: red">B</span>.Name") %&gt;'&gt;&lt;/asp:Label&gt;<br />
&lt;/ItemTemplate&gt;<br />
&lt;/asp:TemplateField&gt;<br />
<br />
<br />
<font face="Verdana">public class A<br />
{<br />
&nbsp;&nbsp;&nbsp; private B _b;<br />
&nbsp;&nbsp;&nbsp; public B B<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_b == null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _b = new B();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return _b;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _b = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
public class B<br />
{<br />
&nbsp;&nbsp;&nbsp; private string _name;<br />
&nbsp;&nbsp;&nbsp; public string Name<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return _name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _name = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
}</font></font></p>
</font>
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1234916.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41313/" target="_blank">[新闻]微软推新型搜索技术"BrowseRank"挑战谷歌</a>]]></description></item><item><title>小技巧(DataTable的排序、检索、合并)</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/03/1234772.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Thu, 03 Jul 2008 06:42:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/03/1234772.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1234772.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/07/03/1234772.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1234772.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1234772.html</trackback:ping><description><![CDATA[<p style="font-size: 10pt">一、排序<br />
<span style="font-size: 8pt">1 获取DataTable的默认视图<br />
2 对视图设置排序表达式<br />
3 用排序后的视图导出的新DataTable替换就DataTable<br />
(Asc升序可省略，多列排序用"，"隔开)</span><br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">DataView&nbsp;dv&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;dt.DefaultView;&nbsp;<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />dv.Sort&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">id&nbsp;Asc,name&nbsp;Desc</span><span style="color: #000000">"</span><span style="color: #000000">;<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />dt&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;dv.ToTable();</span></div>
<p style="font-size: 10pt"><br />
二、检索<br />
<font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体">1 设置查询字符串<br />
</span></font><font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体">2 使用Select方法获取到所有满足条件的数据行对象数组<br />
</span></font><font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体">(多项查询条件间，用and隔开.模糊查询使用 like %)</span></font><font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体"></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">DataRow[]&nbsp;matches&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;dt.Select(</span><span style="color: #000000">"(</span><span style="color: #000000">id&lt;'003')&nbsp;and&nbsp;(name='名字11') and (number like '%2007%')</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;strName&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;matches[</span><span style="color: #000000">0</span><span style="color: #000000">][</span><span style="color: #000000">"</span><span style="color: #000000">name</span><span style="color: #000000">"</span><span style="color: #000000">].ToString();</span></div>
</span></span></font><font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体">
<p style="font-size: 10pt"><br />
</span></font><font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体">三、合并<br />
</span></font><font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体">假定有2个DataTable:Dt1 , Dt2。表结构一样<br />
</span></font><font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体">将Dt2接在Dt1后可采用此方法</span></font><font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体"></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">dt1.Merge(dt2);</span></div>
<p style="font-size: 10pt"></span></font><font face="新宋体" color="#000000" size="1"><span lang="EN-US" style="font-size: 9pt; font-family: 新宋体">&nbsp;</p>
</span></font>
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1234772.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41313/" target="_blank">[新闻]微软推新型搜索技术"BrowseRank"挑战谷歌</a>]]></description></item><item><title>委托的小例子</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/30/1232365.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Mon, 30 Jun 2008 03:42:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/30/1232365.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1232365.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/30/1232365.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1232365.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1232365.html</trackback:ping><description><![CDATA[<p><font face="Verdana">using System;<br />
using System.Collections;<br />
using System.Configuration;<br />
using System.Data;<br />
using System.Linq;<br />
using System.Web;<br />
using System.Web.Security;<br />
using System.Web.UI;<br />
using System.Web.UI.HtmlControls;<br />
using System.Web.UI.WebControls;<br />
using System.Web.UI.WebControls.WebParts;<br />
using System.Xml.Linq;</font></p>
<p><font face="Verdana">public partial class Default2 : System.Web.UI.Page<br />
{<br />
&nbsp;&nbsp;&nbsp; protected void Page_Load(object sender, EventArgs e)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a a1 = new a();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a1.DelegateEvent+=new delegateExample(a1_DelegateEvent);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a1.A1();</font></p>
<p><font face="Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b b1 = new b();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b1.myDelegate = new delegateExample(a1_DelegateEvent);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b1.B1();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public string a1_DelegateEvent(string Classname)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Classname;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
public delegate string delegateExample(string Classname);<br />
public class a<br />
{<br />
&nbsp;&nbsp;&nbsp; public event delegateExample DelegateEvent;<br />
&nbsp;&nbsp;&nbsp; public string A1()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (DelegateEvent != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DelegateEvent("a");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "a1";<br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p><font face="Verdana">}</font></p>
<p><font face="Verdana">public class b<br />
{<br />
&nbsp;&nbsp;&nbsp; public delegateExample myDelegate;<br />
&nbsp;&nbsp;&nbsp; public string B1()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (myDelegate != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myDelegate("b");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "b1";<br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p><font face="Verdana">}<br />
</font></p>
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1232365.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41312/" target="_blank">[新闻]2008年7月26日IT博客精选</a>]]></description></item><item><title>ASP.NET 2.0 中的客户端脚本</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/20/1226565.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Fri, 20 Jun 2008 06:32:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/20/1226565.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1226565.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/20/1226565.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1226565.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1226565.html</trackback:ping><description><![CDATA[在使用&nbsp;ASP.NET&nbsp;的时候，我们仍然在许多情况下需要使用客户端脚本。以下是笔者根据自己的经验和一些粗浅的研究，对此作一个简要的总结。&nbsp; <br />
<br />
　　一、在&nbsp;HTML&nbsp;里直接写脚本 <br />
<br />
　　这个方法是最简单的，直到如今我写网页的时候也几乎还是使用最多的一种方式。也许一些经常使用&nbsp;RegisterClientScriptBlock&nbsp;的人会觉得这种方法老土，不过在我看来，它除了可以减少编译时间以外，更主要的是可以减少代码量，可读性也要好一些，更或许还可以避免一些潜在的错误。 <br />
<br />
　　但是有些情况下，直接写的方法是很难完成要求的，比如说当脚本需要依赖我们在代码中动态生成的控件时，就必须要采用&nbsp;Register&nbsp;的方法了。 <br />
<br />
　　二、使用&nbsp;Literal&nbsp;控件写脚本 <br />
<br />
　　Literal&nbsp;控件基本上就是写一段文字或代码，所以当然也可以写出客户端脚本来，实质上这个方法与第一个方法基本相同。以我个人来说，此种方法一般是用在写控件上。设想一个情况：我们需要根据某种条件来判断一批具有客户端脚本事件的控件是否显示，当然我们可以使用如&nbsp;Panel&nbsp;一类的容器，可是这些容器多半都要套一个&nbsp;div&nbsp;之类的东西，如果在某种情况下我们不希望这时出现&nbsp;div&nbsp;呢？当然或许是有更好更漂亮的办法，只是我都是简单地用一个&nbsp;Literal&nbsp;了事。^_^ <br />
<br />
　　三、使用&nbsp;Register&nbsp;Script&nbsp;函数 <br />
<br />
　　在&nbsp;ASP.NET&nbsp;1.x&nbsp;中，Page&nbsp;类提供了&nbsp;RegisterClientScriptBlock、RegisterOnSubmitStatement&nbsp;以及&nbsp;RegisterStartupScript&nbsp;函数，使得可以在代码中进行&nbsp;ClientScript&nbsp;绑定。不过到了&nbsp;ASP.NET&nbsp;2.0&nbsp;当中，将这些函数统通移到了一个&nbsp;ClientScriptManager&nbsp;类中，并且还添加了类似的&nbsp;RegisterClientScriptInclude&nbsp;函数。在使用这个类的时候，我们可以通过&nbsp;Page.ClientScript&nbsp;来访问。下面介绍一下这几个函数的区别。 <br />
<br />
　　RegisterClientScriptBlock：这个函数将&nbsp;ClientScript&nbsp;加到页面顶部，一般是在紧接着&nbsp;&lt;form&gt;&nbsp;标签的地方。需要注意的是，这个函数中的脚本在写入页面甚至执行的时候，页面的其它元素可能还没有载入完毕，因此可能不能正确地调用页面中的元素。这个函数比较常见的应用是一些客户端事件处理函数。 <br />
<br />
　　RegisterClientScriptInclude：这个函数是&nbsp;ASP.NET&nbsp;2.0&nbsp;新加入的，它一般用于将一个外部的&nbsp;ClientScript&nbsp;文件，比如一个&nbsp;.js&nbsp;文件链接入页面的时候。除此之外，它和&nbsp;RegisterClientScriptBlock&nbsp;基本一样，包括注意事项。 <br />
<br />
　　RegisterStartupScript：这个函数将&nbsp;ClientScript&nbsp;加入到页面的底部，由此带来的好处自然就是可以正确地处理对页面元素的引用了。注意这里的脚本将会在页面的&nbsp;onload&nbsp;事件之前执行。一般来说，这里的代码都是一次性执行的。最常见的比如说是希望页面载入完毕之后弹出一个消息提示框，又或者在一个有框架的页面中，需要在一个页面装载完毕之后更新另一个页面的情况。 <br />
<br />
　　RegisterOnSubmitStatement：这个函数则是将&nbsp;ClientScript&nbsp;与&nbsp;onsubmit&nbsp;事件绑定起来。 <br />
<br />
　　一般的，在使用&nbsp;RegisterClientScriptBlock&nbsp;定义了事件处理函数后，我们可以采用以下的代码将函数与控件关联起来，这里，假定我们已经定义了一个&nbsp;confirmDelete&nbsp;函数： <br />
<br />
1string&nbsp;script&nbsp;=&nbsp;@"return&nbsp;confirmDelete();"; <br />
2btnDelete.Attributes.Add("onclick",&nbsp;script); <br />
　　四、关于&nbsp;RegisterClientScriptResource <br />
<br />
　　除了前一节提过的四个函数外，ASP.NET&nbsp;2.0&nbsp;还增加了一个&nbsp;RegisterClientScriptResource&nbsp;函数。这个函数与前几个的差异在于：它联接的是经过编译成资源的脚本。比如如下一行 <br />
<br />
1Page.ClientScript.RegisterClientScriptResource(this.GetType(),&nbsp;"script_resource.js"); <br />
　　这里的&nbsp;script_resource.js&nbsp;必须是在服务端被编译进&nbsp;assembly&nbsp;中去，其方法是在服务端代码中添加如下一行 <br />
<br />
1[assembly:&nbsp;WebResource("script_resource.js",&nbsp;"application/x-javascript")] <br />
　　如此一来之后，在生成的页面中，我们可以看到类似下面的代码（为了节省版面，我删减了&nbsp;d&nbsp;和&nbsp;t&nbsp;的长度）： <br />
<br />
<br />
<br />
1&lt;script&nbsp;src="/webclient/WebResource.axd?d=oZ35V30&amp;t=63204"&nbsp;type="text/javascript"&gt;&lt;/script&gt; <br />
　　这里的&nbsp;WebResource.axd&nbsp;的请求被送到服务端之后，由一个特定的&nbsp;axd&nbsp;HttpHandler&nbsp;来处理以取得相关的资源（这里就是&nbsp;script-resource.js&nbsp;文件）。在后面我们还可以看到，这个技术还有着更广泛的应用。 <br />
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1226565.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41311/" target="_blank">[新闻]微软每年向Apache捐10万美元支持开源软件</a>]]></description></item><item><title>小技巧（关闭浏览器提示）</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/20/1226561.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Fri, 20 Jun 2008 06:21:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/20/1226561.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1226561.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/20/1226561.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1226561.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1226561.html</trackback:ping><description><![CDATA[<font face="Verdana"><br />
<br />
<p><font face="Verdana">&nbsp;&nbsp;&nbsp; &lt;script language="javascript"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; function IdentifyingPage(IdentifyingImage)<br />
&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; IdentifyingImage.src="../IdentifyingPage.aspx";<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;var bln= true;<br />
&nbsp;function RunOnBeforeUnload() {<br />
&nbsp;&nbsp;&nbsp; if (bln) {window.event.returnValue = '将丢失未保存的数据!';&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp; <br />
&nbsp;}</font></p>
<p><font face="Verdana">&nbsp;&nbsp;&nbsp; &lt;/script&gt;</font></p>
<br />
&lt;body onbeforeunload="RunOnBeforeUnload()"&gt;</font>
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1226561.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41311/" target="_blank">[新闻]微软每年向Apache捐10万美元支持开源软件</a>]]></description></item><item><title>关于IE缓存的解决方案(HTML,JSP,ASP,PHP,C#)（转）</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/18/1224861.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Wed, 18 Jun 2008 10:14:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/18/1224861.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1224861.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/18/1224861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1224861.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1224861.html</trackback:ping><description><![CDATA[禁止服务器端缓存：Response.Expires = 0 或&lt;meta http-equiv="Expires" CONTENT="0"&gt; 禁用客户端缓存。
<p><strong>HTM网页</strong></p>
<p>&lt;META HTTP-EQUIV="pragma" CONTENT="no-cache"&gt;<br />
&lt;META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate"&gt;<br />
&lt;META HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT"&gt;</p>
<p><strong>ASP网页</strong></p>
<p>&lt;%<br />
Response.Expires = -1<br />
Response.ExpiresAbsolute = Now() - 1<br />
Response.cachecontrol = "no-cache"<br />
%&gt;</p>
<p><strong>PHP网页</strong></p>
<p>header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");<br />
header("Cache-Control: no-cache, must-revalidate");<br />
header("Pragma: no-cache");</p>
<p><strong>JSP</strong></p>
<p>response.setHeader("Pragma","No-Cache");<br />
response.setHeader("Cache-Control","No-Cache");<br />
response.setDateHeader("Expires", 0);</p>
<p><strong>C#中禁止cache的方法！</strong></p>
<p>Response.Buffer=true;<br />
Response.ExpiresAbsolute=System.DateTime.Now.AddSeconds(-1);<br />
Response.Expires=0;<br />
Response.CacheControl="no-cache";<br />
<br />
<span style="color: red">注：我是做C#的，C#中页面引用代码后，点击IE上的前进后退按钮，都会提交服务器的。</span></p>
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1224861.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41310/" target="_blank">[新闻]AOL将关闭3个网站以降低成本 集中发力广告</a>]]></description></item><item><title>location.reload() 和 location.replace()的区别和应用</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/18/1224614.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Wed, 18 Jun 2008 05:50:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/18/1224614.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1224614.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/18/1224614.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1224614.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1224614.html</trackback:ping><description><![CDATA[<p class="clsBody"><font face="Verdana, Arial, Helvetica, sans-serif"><font color="#0000ff"><strong>reload</strong></font> 方法，该方法强迫浏览器刷新当前页面。</font><font face="Verdana, Arial, Helvetica, sans-serif"><br />
</font><font face="Verdana, Arial, Helvetica, sans-serif"><font color="#0000ff">语法： </font>location.reload([<em>bForceGet</em>])</font>&nbsp;<font color="#0000ff">参数：</font> <em>bForceGet</em>， 可选参数， 默认为 false，从客户端缓存里取当前页。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true, 则以 <font color="#ff0000">GET</font> 方式，从服务端取最新的页面, 相当于客户端点击 F5("刷新")</p>
<p class="clsBody"><font face="Verdana, Arial, Helvetica, sans-serif"><font color="#0000ff"><strong>replace</strong></font> 方法，该方法通过指定<em>URL</em>替换当前缓存在历史里（客户端）的项目，因此当使用replace方法之后，你不能通过&#8220;前进&#8221;和&#8220;后退&#8221;来访问已经被替换的<em>URL</em>。<br />
</font><font face="Verdana, Arial, Helvetica, sans-serif"><font color="#0000ff">语法： </font>location.replace(<em>URL</em>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参数： <em>URL</em></font></p>
<p class="clsBody">在实际应用的时候，重新刷新页面的时候，我们通常使用： location.reload() 或者是 history.go(0) 来做。因为这种做法就像是客户端点F5刷新页面，所以页面的method="post"的时候，会出现<font style="background-color: #ffcc99">&#8220;网页过期&#8221;</font>的提示。那是因为Session的安全保护机制。可以想到： 当调用 location.reload() 方法的时候， aspx页面此时在服务端内存里已经存在， 因此必定是 IsPostback 的。如果有这种应用： 我们需要<font style="background-color: #ffcc99">重新加载</font>该页面，也就是说我们期望页面能够在服务端重新被创建， 我们期望是 Not IsPostback 的。这里，location.replace() 就可以完成此任务。被replace的页面每次都在服务端重新生成。你可以这么写： location.replace(location.href)</p>
<p align="justify">&nbsp;</p>
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1224614.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41310/" target="_blank">[新闻]AOL将关闭3个网站以降低成本 集中发力广告</a>]]></description></item><item><title>在ASP.NET中使用Global.asax文件</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/17/1223640.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Tue, 17 Jun 2008 03:21:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/17/1223640.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1223640.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/17/1223640.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1223640.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1223640.html</trackback:ping><description><![CDATA[Global.asax 文件，有时候叫做 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 应用程序文件，提供了一种在一个中心位置响应应用程序级或<a href="http://www.zhujiangroad.com/products/14,77.html" target="_blank"><font color="#0000ff">模块</font></a>级事件的方法。你可以使用这个文件实现应用程序安全性以及其它一些任务。下面让我们详细看一下如何在应用程序开发工作中使用这个文件。 <br />
<br />
　　<strong>概述</strong> <br />
<br />
　　Global.asax 位于应用程序根目录下。虽然 Visual Studio .NET 会自动插入这个文件到所有的 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 项目中，但是它实际上是一个可选文件。删除它不会出问题——当然是在你没有使用它的情况下。.asax 文件扩展名指出它是一个应用程序文件，而不是一个使用 aspx 的 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 文件。 <br />
<br />
　　Global.asax 文件被配置为任何（通过 URL 的）直接 HTTP 请求都被自动拒绝，所以用户不能<a href="http://www.zhujiangroad.com/software/" target="_blank"><font color="#0000ff">下载</font></a>或查看其内容。<a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架能够自动识别出对Global.asax 文件所做的任何更改。在 Global.asax 被更改后<a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架会重新启动应用程序，包括关闭所有的浏览器会话，去除所有状态信息，并重新启动应用程序域。 <br />
<br />
　　<strong>编程</strong> <br />
<br />
　　Global.asax 文件继承自HttpApplication 类，它维护一个HttpApplication 对象池，并在需要时将对象池中的对象分配给应用程序。Global.asax 文件包含以下事件： <br />
<br />
　　&#183;Application_Init：在应用程序被实例化或第一次被调用时，该事件被触发。对于所有的HttpApplication 对象实例，它都会被调用。 <br />
<br />
　　&#183;Application_Disposed：在应用程序被销毁之前触发。这是清除以前所用资源的理想位置。 <br />
<br />
　　&#183;Application_Error：当应用程序中遇到一个未处理的异常时，该事件被触发。 <br />
<br />
　　&#183;Application_Start：在HttpApplication 类的第一个实例被创建时，该事件被触发。它允许你创建可以由所有HttpApplication 实例访问的对象。 <br />
<br />
　　&#183;Application_End：在HttpApplication 类的最后一个实例被销毁时，该事件被触发。在一个应用程序的生命周期内它只被触发一次。 <br />
<br />
　　&#183;Application_BeginRequest：在接收到一个应用程序请求时触发。对于一个请求来说，它是第一个被触发的事件，请求一般是用户输入的一个页面请求（URL）。 <br />
<br />
　　&#183;Application_EndRequest：针对应用程序请求的最后一个事件。 <br />
<br />
　　&#183;Application_PreRequestHandlerExecute：在 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架开始执行诸如页面或 Web 服务之类的事件处理程序之前，该事件被触发。 <br />
<br />
　　&#183;Application_PostRequestHandlerExecute：在 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架结束执行一个事件处理程序时，该事件被触发。 <br />
<br />
　　&#183;Applcation_PreSendRequestHeaders：在 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架发送 HTTP 头给请求客户（浏览器）时，该事件被触发。 <br />
<br />
　　&#183;Application_PreSendContent：在 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架发送内容给请求客户（浏览器）时，该事件被触发。 <br />
<br />
　　&#183;Application_AcquireRequestState：在 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架得到与当前请求相关的当前状态（Session 状态）时，该事件被触发。 <br />
<br />
　　&#183;Application_ReleaseRequestState：在 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架执行完所有的事件处理程序时，该事件被触发。这将导致所有的状态<a href="http://www.zhujiangroad.com/products/14,77.html" target="_blank"><font color="#0000ff">模块</font></a>保存它们当前的状态数据。 <br />
<br />
　　&#183;Application_ResolveRequestCache：在 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架完成一个授权请求时，该事件被触发。它允许缓存<a href="http://www.zhujiangroad.com/products/14,77.html" target="_blank"><font color="#0000ff">模块</font></a>从缓存中为请求提供服务，从而绕过事件处理程序的执行。 <br />
<br />
　　&#183;Application_UpdateRequestCache：在 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 页面框架完成事件处理程序的执行时，该事件被触发，从而使缓存<a href="http://www.zhujiangroad.com/products/14,77.html" target="_blank"><font color="#0000ff">模块</font></a>存储响应数据，以供响应后续的请求时使用。 <br />
<br />
　　&#183;Application_AuthenticateRequest：在安全<a href="http://www.zhujiangroad.com/products/14,77.html" target="_blank"><font color="#0000ff">模块</font></a>建立起当前用户的有效的身份时，该事件被触发。在这个时候，用户的凭据将会被验证。 <br />
<br />
　　&#183;Application_AuthorizeRequest：当安全<a href="http://www.zhujiangroad.com/products/14,77.html" target="_blank"><font color="#0000ff">模块</font></a>确认一个用户可以访问资源之后，该事件被触发。 <br />
<br />
　　&#183;Session_Start：在一个新用户访问应用程序 Web 站点时，该事件被触发。 <br />
<br />
　　&#183;Session_End：在一个用户的会话超时、结束或他们离开应用程序 Web 站点时，该事件被触发。 <br />
<br />
　　这个事件列表看起来好像多得吓人，但是在不同环境下这些事件可能会非常有用。 <br />
<br />
　　使用这些事件的一个关键问题是知道它们被触发的顺序。Application_Init 和Application_Start 事件在应用程序第一次启动时被触发一次。相似地，Application_Disposed 和 Application_End 事件在应用程序终止时被触发一次。此外，基于会话的事件（Session_Start 和 Session_End）只在用户进入和离开站点时被使用。其余的事件则处理应用程序请求，这些事件被触发的顺序是： <br />
<br />
　　&#183;Application_BeginRequest <br />
<br />
　　&#183;Application_AuthenticateRequest <br />
<br />
　　&#183;Application_AuthorizeRequest <br />
<br />
　　&#183;Application_ResolveRequestCache <br />
<br />
　　&#183;Application_AcquireRequestState <br />
<br />
　　&#183;Application_PreRequestHandlerExecute <br />
<br />
　　&#183;Application_PreSendRequestHeaders <br />
<br />
　　&#183;Application_PreSendRequestContent <br />
<br />
　　&#183;&lt;&lt;执行代码&gt;&gt; <br />
<br />
　　&#183;Application_PostRequestHandlerExecute <br />
<br />
　　&#183;Application_ReleaseRequestState <br />
<br />
　　&#183;Application_UpdateRequestCache <br />
<br />
　　&#183;Application_EndRequest <br />
<br />
　　这些事件常被用于安全性方面。下面这个 C# 的例子演示了不同的Global.asax 事件，该例使用Application_Authenticate 事件来完成通过 cookie 的基于表单（form）的身份验证。此外，Application_Start 事件填充一个应用程序变量，而Session_Start 填充一个会话变量。Application_Error 事件显示一个简单的消息用以说明发生的错误。 <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>protected void Application_Start(Object sender, EventArgs e) { <br />
            　Application["Title"] = "Builder.com Sample"; <br />
            } <br />
            protected void Session_Start(Object sender, EventArgs e) { <br />
            　Session["startValue"] = 0; <br />
            } <br />
            protected void Application_AuthenticateRequest(Object sender, EventArgs e) { <br />
            　// Extract the forms authentication cookie <br />
            　string cookieName = FormsAuthentication.FormsCookieName; <br />
            　HttpCookie authCookie = Context.Request.Cookies[cookieName]; <br />
            　if(null == authCookie) { <br />
            　　// There is no authentication cookie. <br />
            　　return; <br />
            　} <br />
            　FormsAuthenticationTicket authTicket = null; <br />
            　try { <br />
            　　authTicket = FormsAuthentication.Decrypt(authCookie.Value); <br />
            　} catch(Exception ex) { <br />
            　　// Log exception details (omitted for simplicity) <br />
            　　return; <br />
            　} <br />
            　if (null == authTicket) { <br />
            　　// Cookie failed to decrypt. <br />
            　　return; <br />
            　} <br />
            　// When the ticket was created, the UserData property was assigned <br />
            　// a pipe delimited string of role names. <br />
            　string[2] roles <br />
            　roles[0] = "One" <br />
            　roles[1] = "Two" <br />
            　// Create an Identity object <br />
            　FormsIdentity id = new FormsIdentity( authTicket ); <br />
            　// This principal will flow throughout the request. <br />
            　GenericPrincipal principal = new GenericPrincipal(id, roles); <br />
            　// Attach the new principal object to the current HttpContext object <br />
            　Context.User = principal; <br />
            } <br />
            protected void Application_Error(Object sender, EventArgs e) { <br />
            　Response.Write("Error encountered."); <br />
            } </td>
        </tr>
    </tbody>
</table>
<br />
　　这个例子只是很简单地使用了一些Global.asax 文件中的事件；重要的是要意识到这些事件是与整个应用程序相关的。这样，所有放在其中的方法都会通过应用程序的代码被提供，这就是它的名字为Global 的原因。 <br />
<br />
　　这里是前面的例子相应的 <a href="http://www.zhujiangroad.com/program/VB.html" target="_blank"><font color="#0000ff">VB</font></a>.NET 代码： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs) <br />
            　Application("Title") = "Builder.com Sample" <br />
            End Sub <br />
            Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs) <br />
            　Session("startValue") = 0 <br />
            End Sub <br />
            Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As <br />
            EventArgs) <br />
            　&#8217; Extract the forms authentication cookie <br />
            　Dim cookieName As String <br />
            　cookieName = FormsAuthentication.FormsCookieName <br />
            　Dim authCookie As HttpCookie <br />
            　authCookie = Context.Request.Cookies(cookieName) <br />
            　If (authCookie Is Nothing) Then <br />
            　　&#8217; There is no authentication cookie. <br />
            　　Return <br />
            　End If <br />
            　Dim authTicket As FormsAuthenticationTicket <br />
            　authTicket = Nothing <br />
            　Try <br />
            　　authTicket = FormsAuthentication.Decrypt(authCookie.Value) <br />
            　　Catch ex As Exception <br />
            　　&#8217; Log exception details (omitted for simplicity) <br />
            　　Return <br />
            　End Try <br />
            　Dim roles(2) As String <br />
            　roles(0) = "One" <br />
            　roles(1) = "Two" <br />
            　Dim id As FormsIdentity <br />
            　id = New FormsIdentity(authTicket) <br />
            　Dim principal As GenericPrincipal <br />
            　principal = New GenericPrincipal(id, roles) <br />
            　&#8217; Attach the new principal object to the current HttpContext object <br />
            　Context.User = principal <br />
            End Sub <br />
            <br />
            Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs) <br />
            　Response.Write("Error encountered.") <br />
            End Sub </td>
        </tr>
    </tbody>
</table>
<br />
　　<strong>资源</strong> <br />
<br />
　　Global.asax 文件是 <a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 应用程序的中心点。它提供无数的事件来处理不同的<span style="color: red">应用程序级任务</span>，比如用户身份验证、应用程序启动以及处理用户会话等。你应该熟悉这个可选文件，这样就可以构建出健壮的<a href="http://www.zhujiangroad.com/program/asp.html" target="_blank"><font color="#0000ff">ASP</font></a>.NET 应用程序。 
<img src ="http://www.cnblogs.com/cuihongyu3503319/aggbug/1223640.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41309/" target="_blank">[新闻]谷歌网页索引数量突破1万亿个</a>]]></description></item><item><title>加密技术在企业数据安全中的应用(转)</title><link>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/04/1213946.html</link><dc:creator>宏宇</dc:creator><author>宏宇</author><pubDate>Wed, 04 Jun 2008 14:10:00 GMT</pubDate><guid>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/04/1213946.html</guid><wfw:comment>http://www.cnblogs.com/cuihongyu3503319/comments/1213946.html</wfw:comment><comments>http://www.cnblogs.com/cuihongyu3503319/archive/2008/06/04/1213946.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/cuihongyu3503319/comments/commentRss/1213946.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/cuihongyu3503319/services/trackbacks/1213946.html</trackback:ping><description><![CDATA[随着大型企业管理软件的发展，其应用越来越广泛，企业数据平台涉及局域网、广域网、Internet等，在各类系统中保存的企业关键数据量也越来越大，许多数据需要保存数十年以上，甚至是永久性保存。于是关键业务数据成了企业生存的命脉和宝贵的资源，数据安全性问题越来越突出。如何增强企业软件系统的安全性、保密性、真实性、完整性，成为每一位软件开发人员关注的焦点。
<p>　　为了解决关键业务的数据安全问题，首先对数据系统进行全面、可靠、安全和多层次的备份是必不可少的，除此以外，各种安全产品，无论防火墙、防病毒、防黑客、防入侵等等，都或多或少地肩负着一些保护数据的责任。从保护数据的角度讲，对数据安全这个广义概念，可以细分为三部分：数据加密、数据传输安全和身份认证管理。</p>
<p>　　<span class="hei"><span lang="EN-US" style="font-family: Wingdings">l </span></span>数据加密就是按照确定的密码算法将敏感的明文数据变换成难以识别的密文数据，通过使用不同的密钥，可用同一加密算法将同一明文加密成不同的密文。当需要时，可使用密钥将密文数据还原成明文数据，称为解密。这样就可以实现数据的保密性。数据加密被公认为是保护数据传输安全惟一实用的方法和保护存储数据安全的有效方法，它是数据保护在技术上最重要的防线。</p>
<p>　　<span class="hei"><span lang="EN-US" style="font-family: Wingdings">l </span></span>数据传输安全是指数据在传输过程中必须要确保数据的安全性，完整性和不可篡改性。</p>
<p>　　<span class="hei"><span lang="EN-US" style="font-family: Wingdings">l </span></span>身份认证的目的是确定系统和网络的访问者是否是合法用户。主要采用登录密码、代表用户身份的物品（如智能卡、IC卡等）或反映用户生理特征的标识鉴别访问者的身份。</p>
<h3>　　数据加密</h3>
<p>　　数据加密技术是最基本的安全技术，被誉为信息安全的核心，最初主要用于保证数据在存储和传输过程中的保密性。它通过变换和置换等各种方法将被保护信息置换成密文，然后再进行信息的存储或传输，即使加密信息在存储或者传输过程为非授权人员所获得，也可以保证这些信息不为其认知，从而达到保护信息的目的。该方法的保密性直接取决于所采用的密码算法和密钥长度。</p>
<p>　　根据密钥类型不同可以将现代密码技术分为两类：对称加密算法（私钥密码体系）和非对称加密算法（公钥密码体系）。在对称加密算法中，数据加密和解密采用的都是同一个密钥，因而其安全性依赖于所持有密钥的安全性。对称加密算法的主要优点是加密和解密速度快，加密强度高，且算法公开，但其最大的缺点是实现密钥的秘密分发困难，在大量用户的情况下密钥管理复杂，而且无法完成身份认证等功能，不便于应用在网络开放的环境中。目前最著名的对称加密算法有数据加密标准DES和欧洲数据加密标准IDEA等，目前加密强度最高的对称加密算法是高级加密标准AES。</p>
<p>　　对称加密算法、非对称加密算法和不可逆加密算法可以分别应用于数据加密、身份认证和数据安全传输。</p>
<p>　　<span class="hei"><span lang="EN-US" style="font-family: Wingdings">l </span></span><strong>对称加密算法</strong></p>
<p>　　对称加密算法是应用较早的加密算法，技术成熟。在对称加密算法中，数据发信方将明文（原始数据）和加密密钥一起经过特殊加密算法处理后，使其变成复杂的加密密文发送出去。收信方收到密文后，若想解读原文，则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密，才能使其恢复成可读明文。在对称加密算法中，使用的密钥只有一个，发收信双方都使用这个密钥对数据进行加密和解密，这就要求解密方事先必须知道加密密钥。对称加密算法的特点是算法公开、计算量小、加密速度快、加密效率高。不足之处是，交易双方都使用同样钥匙，安全性得不到保证。此外，每对用户每次使用对称加密算法时，都需要使用其他人不知道的惟一钥匙，这会使得发收信双方所拥有的钥匙数量成几何级数增长，密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难，主要是因为密钥管理困难，使用成本较高。在计算机专网系统中广泛使用的对称加密算法有DES、IDEA和AES。</p>
<p>　　传统的DES由于只有56位的密钥，因此已经不适应当今分布式开放网络对数据加密安全性的要求。1997年RSA数据安全公司发起了一项&#8220;DES挑战赛&#8221;的活动，志愿者四次分别用四个月、41天、56个小时和22个小时破解了其用56位密钥DES算法加密的密文。即DES加密算法在计算机速度提升后的今天被认为是不安全的。</p>
<p>　　AES是美国联邦政府采用的商业及政府数据加密标准，预计将在未来几十年里代替DES在各个领域中得到广泛应用。AES提供128位密钥，因此，128位AES的加密强度是56位DES加密强度的1021倍还多。假设可以制造一部可以在1秒内破解DES密码的机器，那么使用这台机器破解一个128位AES密码需要大约149亿万年的时间。（更深一步比较而言，宇宙一般被认为存在了还不到200亿年）因此可以预计，美国国家标准局倡导的AES即将作为新标准取代DES。</p>
<p>　　<span class="hei"><span lang="EN-US" style="font-family: Wingdings">l </span></span><strong>不对称加密算法</strong></p>
<p>　　不对称加密算法使用两把完全不同但又是完全匹配的一对钥匙—公钥和私钥。在使用不对称加密算法加密文件时，只有使用匹配的一对公钥和私钥，才能完成对明文的加密和解密过程。加密明文时采用公钥加密，解密密文时使用私钥才能完成，而且发信方（加密者）知道收信方的公钥，只有收信方（解密者）才是唯一知道自己私钥的人。不对称加密算法的基本原理是，如果发信方想发送只有收信方才能解读的加密信息，发信方必须首先知道收信方的公钥，然后利用收信方的公钥来加密原文；收信方收到加密密文后，使用自己的私钥才能解密密文。显然，采用不对称加密算法，收发信双方在通信之前，收信方必须将自己早已随机生成的公钥送给发信方，而自己保留私钥。由于不对称算法拥有两个密钥，因而特别适用于分布式系统中的数据加密。广泛应用的不对称加密算法有RSA算法和美国国家标准局提出的DSA。以不对称加密算法为基础的加密技术应用非常广泛。</p>
<p>　　<span class="hei"><span lang="EN-US" style="font-family: Wingdings">l </span></span><strong>不可逆加密算法</strong></p>
<p>　　不可逆加密算法的特征是加密过程中不需要使用密钥，输入明文后由系统直接经过加密算法处理成密文，这种加密后的数据是无法被解密的，只有重新输入明文，并再次经过同样不可逆的加密算法处理，得到相同的加密密文并被系统重新识别后，才能真正解密。显然，在这类加密过程中，加密是自己，解密还得是自己，而所谓解密，实际上就是重新加一次密，所应用的&#8220;密码&#8221;也就是输入的明文。不可逆加密算法不存在密钥保管和分发问题，非常适合在分布式网络系统上使用，但因加密计算复杂，工作量相当繁重，通常只在数据量有限的情形下使用，如广泛应用在计算机系统中的口令加密，利用的就是不可逆加密算法。近年来，随着计算机系统性能的不断提高，不可逆加密的应用领域正在逐渐增大。在计算机网络中应用较多不可逆加密算法的有RSA公司发明的MD5算法和由美国国家标准局建议的不可逆加密标准SHS(Secure Hash Standard:安全杂乱信息标准)等。</p>
<h3>　　传输安全</h3>
<p>　　数据传输加密技术目的是对传输中的数据流加密，以防止通信线路上的窃听、泄漏、篡改和破坏。数据传输的完整性通常通过数字签名的方式来实现，即数据的发送方在发送数据的同时利用单向的不可逆加密算法Hash函数或者其它信息文摘算法计算出所传输数据的消息文摘，并将该消息文摘作为数字签名随数据一同发送。接收方在收到数据的同时也收到该数据的数字签名，接收方使用相同的算法计算出接收到的数据的数字签名，并将该数字签名和接收到的数字签名进行比较，若二者相同，则说明数据在传输过程中未被修改，数据完整性得到了保证。</p>
<p>　　Hash算法也称为消息摘要或单向转换，是一种不可逆加密算法，称它为单向转换是因为：</p>
<p>　　1）双方必须在通信的两个端头处各自执行Hash函数计算；</p>
<p>　　2）使用Hash函数很容易从消息计算出消息摘要，但其逆向反演过程以目前计算机的运算能力几乎不可实现。</p>
<p>　　Hash散列本身就是所谓加密检查，通信双方必须各自执行函数计算来验证消息。举例来说，发送方首先使用Hash算法计算消息检查和，然后将计算结果A封装进数据包中一起发送；接收方再对所接收的消息执行Hash算法计算得出结果B，并将B与A进行比较。如果消息在传输中遭篡改致使B与A不一致，接收方丢弃该数据包。</p>
<p>　　有两种最常用的Hash函数：</p>
<p>　　&#183;MD5（消息摘要5）：MD5对MD4做了改进，计算速度比MD4稍慢，但安全性能得到了进一步改善。MD5在计算中使用了64个32位常数，最终生成一个128位的完整性检查和。</p>
<p>　　&#183;SHA 安全Hash算法：其算法以MD5为原型。 SHA在计算中使用了79个32位常数，最终产生一个160位完整性检查和。SHA检查和长度比MD5更长，因此安全性也更高。</p>
<h3>　　身份认证</h3>
<p>　　身份认证要求参与安全通信的双方在进行安全通信前，必须互相鉴别对方的身份。保护数据不仅仅是要让数据正确、长久地存在，更重要的是，要让不该看到数据的人看不到。这方面，就必须依靠身份认证技术来给数据加上一把锁。数据存在的价值就是需要被合理访问，所以，建立信息安全体系的目的应该是保证系统中的数据只能被有权限的人访问，未经授权的人则无法访问到数据。如果没有有效的身份认证手段，访问者的身份就很容易被伪造，使得未经授权的人仿冒有权限人的身份，这样，任何安全防范体系就都形同虚设，所有安全投入就被无情地浪费了。</p>
<p>　　在企业管理系统中，身份认证技术要能够密切结合企业的业务流程，阻止对重要资源的非法访问。身份认证技术可以用于解决访问者的物理身份和数字身份的一致性问题，给其他安全技术提供权限管理的依据。所以说，身份认证是整个信息安全体系的基础。</p>
<p>　　由于网上的通信双方互不见面，必须在交易时（交换敏感信息时）确认对方的真实身份； 身份认证指的是用户身份的确认技术，它是网络安全的第一道防线，也是最重要的一道防线。</p>
<p>　　在公共网络上的认证，从安全角度分有两类：一类是请求认证者的秘密信息（例如：口令）在网上传送的口令认证方式，另一类是使用不对称加密算法，而不需要在网上传送秘密信息的认证方式，这类认证方式中包括数字签名认证方式。</p>
<p>　　<span class="hei"><span lang="EN-US" style="font-family: Wingdings">l </span></span><strong>口令认证方式</strong></p>
<p>　　口令认证必须具备一个前提：请求认证者必须具有一个 ID，该ID必须在认证者的用户数据库（该数据库必须包括ID和口令）中是唯一的。同时为了保证认证的有效性必须考虑到以下问题：</p>
<p>　　&#183; 求认证者的口令必须是安全的。</p>
<p>　　&#183; 在传输过程中，口令不能被窃看，替换。</p>
<p>　　&#183;请求认证者在向认证者请求认证前，必须确认认证者的真实身份。否则会把口令发给冒充的认证者。</p>
<p>　　口令认证方式还有一个最大的安全问题就是系统的管理员通常都能得到所有用户的口令。因此，为了避免这样的安全隐患，通常情况下会在数据库中保存口令的Hash值，通过验证Hash值的方法来认证身份。</p>
<p>　　<span class="hei"><span lang="EN-US" style="font-family: Wingdings">l </span></span><strong>使用不对称加密算法的认证方式 （数字证书方式）</strong></p>
<p>　　使用不对称加密算法的认证