通过使用客户端证书调用 Web 服务以便在 ASP.NET Web 应用程序中进行身份验证zz
概要
本文讨论如何从 ASP.NET Web 应用程序向 Web 服务传递客户端证书以进行身份验证。
注意:本文的步骤同样适用于使用 HttpWebRequest 类执行直接 HTTP 请求的情况(如果不调用 Web 服务)。
回到顶端
简介
通常,Web 服务必须对调用该 Web 服务的应用程序执行身份验证。Web 服务必须对调用应用程序执行身份验证,然后才能执行授权。其中一种身份验证技术就是要求调用该 Web 服务的应用程序提供客户端证书。
如果一个 ASP.NET Web 应用程序试图调用使用证书身份验证的 Web 服务,您可能会收到“access denied”(访问被拒绝)错误信息。如果控制台应用程序或 Microsoft Windows 窗体应用程序调用相同的 Web 服务,则不会收到错误信息。
之所以会发生这种行为,是因为计算机维护两种不同的证书存储: • 本地机器存储:ASP.NET Web 应用程序在此类存储中进行查找以定位客户端证书。
• 本地用户存储:交互式用户应用程序在此类存储中进行查找以定位客户端证书。
通常,如果交互式用户应用程序安装客户端证书,会将客户端证书安装在本地用户存储中。因此,客户端证书可用于交互式用户应用程序。但是,客户端证书不用于 ASP.NET Web 应用程序。
回到顶端
更多信息
要使 ASP.NET Web 应用程序能够使用客户端证书,您必须在本地机器存储中安装客户端证书。如果您在本地机器存储中安装客户端证书,则该客户端证书仅对管理员组中的用户帐户和安装该客户端证书的用户可用。因此,您必须向用于运行 ASP.NET Web 应用程序的用户帐户授权,使其能够访问客户端证书。
注意:必须安装 Microsoft .NET Framework 1.1 Service Pack 1 (SP1) 才能在本地机器存储中使用客户端证书。
此外,在 ASP.NET Web 应用程序调用 Web 服务时,该应用程序必须从证书存储中导出客户端证书,然后将其添加到 Web 服务调用中。
回到顶端
安装客户端证书并向用户帐户授予访问权限
要安装客户端证书,并向用于运行 ASP.NET Web 应用程序的用户帐户授权,使其能够访问客户端证书,请执行下列步骤。
步骤 1:在本地机器存储中安装客户端证书
如果您在 PKCS#12 (.pfx) 文件中有客户端证书,则可以使用 Microsoft Windows HTTP 服务证书配置工具 (WinHttpCertCfg.exe) 来安装客户端证书并向其他用户帐户(如网络服务帐户)授权,使其能够访问客户端证书。为此,请按照下列步骤操作: 1. 下载然后安装 Microsoft Windows HTTP 服务证书配置工具。要获得此工具,请访问下面的 Microsoft 网站:
http://www.microsoft.com/downloads/details.aspx?familyid=c42e27ac-3409-40e9-8667-c748e422833f(http://www.microsoft.com/downloads/details.aspx?familyid=c42e27ac-3409-40e9-8667-c748e422833f)
2. 在命令提示符处运行以下命令:
WinHttpCertCfg.exe –i PfxFile -c LOCAL_MACHINEMY -p Password
注意:PfxFile 是 .pfx 文件的名称。Password 是 .pfx 文件的密码。如果该文件不要求密码,则省略参数 -p。
通常,WinHttpCertCfg.exe 文件位于以下文件夹中:
C:Program FilesWindows Resource KitsTools
如果您无权访问 .pfx 文件,并已经在运行 Microsoft Windows Server 2003 或 Microsoft Windows 2000 Server 的计算机上安装了 Microsoft 证书服务,则可以提出请求,并直接在本地机器存储中安装客户端证书。为此,请按照下列步骤操作: 1. 使用具有管理员凭据的用户帐户登录到客户机。
2. 在 Microsoft Internet Explorer 中,访问证书颁发机构 (CA) 网站。例如,如果 CA 服务器名为 CAServer,请访问下面的网站:
http://CAServer/certsrv
3. 在“选择一个任务”下,单击“申请一个证书”然后单击“高级证书申请”。
4. 单击“创建并向此 CA 提交一个申请”。
5. 在“高级证书申请”窗体中,输入姓名和电子邮件地址。
6. 在“需要的证书类型”部分,单击“客户端身份验证证书”。
7. 在“密钥选项”部分,单击以选中“将证书保存在本地计算机存储中”复选框,然后单击“提交”。
请注意客户端证书的申请 ID。
8. 在“潜在的脚本冲突”对话框中,单击“是”。
9. 在 CA 颁发客户端证书后,单击“主页”,然后单击“查看挂起的证书申请的状态”。
10. 在“请选择您要查看的证书申请”下,单击您在步骤 7 中提交的证书申请。
11. 单击“安装此证书”,然后在“潜在的脚本冲突”对话框中单击“是”。
步骤 2:配置对客户端证书的访问权限
在此步骤中,您必须向 ASP.NET 帐户授予权限,使其能够访问存储在本地机器存储中的客户端证书。在 Windows Server 2003 中,网络服务帐户是运行 Web 应用程序的默认帐户。因此,您必须向网络服务帐户授权使其能够访问该证书。如果您配置了一个自定义帐户以运行 ASP.NET,则必须向该自定义帐户授予访问权限。
注意:在 Microsoft Internet Information Server (IIS) 5.0 中,ASP.NET 在 ASPNET 帐户而非网络服务帐户下运行。因此,在运行 IIS 5.0 的计算机上,您必须向 ASPNET 帐户授予权限。
要向特定的用户帐户授予访问权限,请在命令提示符处运行以下命令:
WinHttpCertCfg.exe -g -c LOCAL_MACHINEMY -s "IssuedToName" -a "AccountName"
注意:AccountName 是本地计算机帐户名或域帐户名。IssuedToName 是客户端证书颁发对象的公司名或域名。该命令包含一个不区分大小写的搜索字符串。该搜索字符串查找第一个主题名称中包含该字符串的枚举证书。
下面的命令行命令是一个如何在 Microsoft Internet 信息服务 (IIS) 6.0 中向网络服务帐户授权,使其能够访问客户端证书的示例:
WinHttpCertCfg.exe -g -c LOCAL_MACHINEMY -s "IssuedToName" -a "NT AUTHORITYNetworkService"
下面的命令行命令是一个如何在 IIS 5.0 中向 ASPNET 帐户授权,使其能够访问客户端证书的示例:
WinHttpCertCfg.exe -g -c LOCAL_MACHINEMY -s "IssuedToName" -a "ASPNET"
注意:如果您使用 Windows HTTP 服务证书配置工具,则可以将导入客户端证书的过程与配置对客户端证书的访问权限的过程合并为一个步骤。例如,下面的命令行命令将执行这两个过程:
Winhttpcertcfg.exe -i PFXFile -c LOCAL_MACHINEMy -a “AccountName”
步骤 3:将客户端证书从本地用户存储复制到本地机器存储
如果一个交互式应用程序(如 Windows 窗体应用程序)或命令行应用程序能够访问客户端证书,则该客户端证书已经存储在本地用户存储中。但是,如果一个服务应用程序(如 ASP.NET Web 应用程序)不能访问同一个客户端证书,则该客户端证书可能未存储在本地机器存储中。
本步骤将介绍如何使用证书导出向导将本地用户存储中的客户端证书复制到本地机器存储中。
注意:如果客户端证书已经在本地机器存储中,或者如果您能够按照步骤 1 所述直接在本地机器存储中安装客户端证书,请转到步骤 4。但是,如果您使用了步骤 3,则之后必须返回步骤 2 以授予对客户端证书的访问权限。
要将客户端证书复制到本地机器存储中,请执行下列步骤: 1. 单击“开始”,单击“运行”,键入 mmc,然后单击“确定”。
2. 在“文件”菜单上,单击“添加/删除管理单元”,然后单击“添加”。
3. 在“添加独立管理单元”对话框中,依次单击“证书”、“添加”、“计算机帐户”、“下一步”,然后单击“完成”。
4. 在“添加独立管理单元”对话框中,依次单击“证书”、“添加”、“我的用户帐户”,然后单击“完成”。
5. 单击“关闭”,然后单击“确定”。
6. 要从本地用户存储中导出客户端证书,请执行下列步骤:a. 依次展开“证书 - 当前用户”、“个人”,然后单击“证书”。
b. 右键单击此客户端证书,依次单击“所有任务”、“导出”,然后单击“下一步”。
c. 如果“是,导出私钥”选项不可用,则 ASP.NET Web 应用程序不能使用该客户端证书。您必须获取其他客户端证书。为此,请按照步骤 1 和步骤 2 中的说明进行操作。否则,单击“是,导出私钥”,然后单击两次“下一步”。
d. 在“密码”框和“确认密码”框中,键入密码,然后单击“下一步”。
e. 在“文件名”框中,键入文件名。单击“下一步”,然后单击“完成”。
f. 在“证书导出向导”对话框中,单击“确定”。
7. 要将客户端证书导入到本地机器存储中,请执行下列步骤:a. 展开“证书(本地计算机)”,然后展开“个人”。
b. 右键单击“证书”,依次单击“所有任务”、“导入”,然后单击“下一步”。
c. 在“文件名”框中,键入您在步骤 6e 中指定的文件名,然后单击“下一步”。
d. 在“密码”框中,键入您在步骤 6d 中指定的密码,然后单击两次“下一步”。
e. 单击“完成”,然后单击“确定”。
步骤 4:安装 CA 根证书
如果客户端证书已经由外部 CA(如 VeriSign)签名,或者如果您已经安装了 CA 根证书,则可以省略步骤 4。
默认情况下,Windows 已将许多外部 CA 根证书预安装在受信任的根证书存储中。
验证是否安装了根证书
要验证是否安装了 CA 根证书,请执行下列步骤: 1. 单击“开始”,单击“运行”,键入 mmc,然后单击“确定”。
2. 在“文件”菜单上,单击“添加/删除管理单元”,然后单击“添加”。
3. 在“添加独立管理单元”对话框中,依次单击“证书”、“添加”、“计算机帐户”、“下一步”,然后单击“完成”。
4. 单击“关闭”,然后单击“确定”。
5. 依次展开“证书(本地计算机)”、“受信任的根证书颁发机构”,然后单击“证书”。
6. 在右窗格中,请确认列出了要使用的 CA 根证书。
安装根证书
如果没有列出要使用的 CA 根证书,则必须安装此根证书。如果要使用的 CA 根证书颁发在证书文件(如 .cer 文件、.der 文件、或 .pfx 文件)中,请执行下列步骤: 1. 展开“证书(本地计算机)”,右键单击“受信任的根证书颁发机构”,单击“所有任务”,然后单击“导入”。
2. 在“证书导入向导”对话框中,单击“下一步”,然后在“文件名”框中,键入证书文件的名称,然后单击两次“下一步”。
3. 单击“完成”,然后单击“确定”。
申请根证书
如果要使用的 CA 包括在 Microsoft 证书服务安装数据库中,那么您可以申请根证书。为此,请按照下列步骤操作: 1. 在 Internet Explorer 中,访问 CA 网站。例如,如果 CA 服务器名为 CAServer,请访问下面的网站:
http://CAServer/certsrv
2. 单击“下载一个 CA 证书,证书链或 CRL”,然后单击“下载 CA 证书”。
3. 在“文件下载”对话框中,单击“保存”。
4. 在“另存为”对话框中,输入要保存证书文件的位置,然后单击“保存”。
5. 保存根证书文件后,使用“安装根证书”部分中的步骤在受信任的根证书颁发机构存储中安装证书文件。
回到顶端
调用 Web 服务
当您在本地机器存储或本地用户存储中安装客户端证书后,您就可以从 ASP.NET Web 应用程序中访问该客户端证书以调用 Web 服务。对于 Windows 窗体应用程序或 ASP.NET Web 应用程序,访问客户端证书的步骤是相同的。
如果使用的是 .NET Framework 1.1,则必须先将密钥导出到一个 DER 编码文件中。必须导出密钥的原因是 System.Security.Cryptography.X509Certificates.X509Certificate 类中不包含可以直接访问证书存储中的证书详细信息的方法。因此,应用程序必须从 DER 编码文件中读取证书的详细信息。
注意:Web Services Enhancements 2.0 for Microsoft .NET (WSE) 为应用程序提供了一种从证书存储中直接检索证书详细信息的方法。
下面的 C# 示例代码显示如何通过传递客户端证书进行身份验证来调用 Web 服务。using System.Security.Cryptography.X509Certificates;
...
public void CallWebService()
{
// TODO: Replace <C:WSClientCert.cer> with the path of your certificate file.
string certPath = @"<C:WSClientCert.cer>";
// Create an instance of the Web service proxy.
WebSvc.math mathservice = new WebSvc.math();
// TODO: Replace <https://wsserver/securemath/math.asmx> with a valid URL.
mathservice.Url = @"<https://wsserver/securemath/math.asmx>";
// Create an X509Certificate object from the information
// in the certificate export file, and then add the certificate to the
// ClientCertificates collection of the Web service proxy.
mathservice.ClientCertificates.Add(
X509Certificate.CreateFromCertFile(certPath));
long lngResult = 0;
try
{
lngResult = mathservice.Add(Int32.Parse(operand1.Text),
Int32.Parse(operand2.Text));
string result = lngResult.ToString();
}
catch(Exception ex)
{
if(ex is WebException)
{
WebException we = ex as WebException;
WebResponse webResponse = we.Response;
throw new Exception("Exception calling method. " + ex.Message);
}
}
}
回到顶端
Web Services Enhancements 2.0 for Microsoft .NET
Web Services Enhancements 2.0 for Microsoft .NET (WSE) 是一个 Microsoft .NET 类库,它使用最新的 Web 服务协议来创建 Web 服务。这些协议包括:• WS-Security
• WS-SecureConversation
• WS-Trust
• WS-Policy
• WS-SecurityPolicy
• WS-Addressing
• WS-Attachments
注意:WSE 不作为 .NET Framework 的一部分包括在内。要获得 WSE,请访问下面的 Microsoft 网站:
http://www.microsoft.com/downloads/details.aspx?FamilyId=FC5F06C5-821F-41D3-A4FE-6C7B56423841(http://www.microsoft.com/downloads/details.aspx?FamilyId=FC5F06C5-821F-41D3-A4FE-6C7B56423841)
您不必使用这些协议中的任何一种来访问要求客户端证书身份验证的 Web 服务。但是,您可能要使用 Microsoft.Web.Services2.Security.X509 类。Microsoft.Web.Services2.Security.X509 类包含可以直接访问证书存储中的客户端证书的方法。如果您使用这些方法,就不必将证书导出到文件中。
下面的 C# 示例代码显示如何在本地机器存储中查找第一个名为 SecureMathClient 的证书。然后,该示例代码使用此证书调用 math Web 服务的 Add 方法。math Web 服务要求客户端证书。...
// TODO: Replace <SecureMathClient> with the name of the client certificate.
string certName = "<SecureMathClient>";
// WSE 2.0 method
X509CertificateStore store =
X509CertificateStore.LocalMachineStore(X509CertificateStore.MyStore);
store.OpenRead();
// Look for the first certificate that is named SecureMathClient.
// Look in the local machine store.
X509CertificateCollection col=
(X509CertificateCollection)store.FindCertificateBySubjectString(certName);
X509Certificate cert =null;
try
{
// This sample obtains the first matching certificate from the collection.
cert = col[0];
}
catch(Exception ex)
{
throw new Exception("Certificate not Found!");
}
// Create an instance of the Web service proxy.
math mathservice = new math();
// TODO: Replace <https://wsserver/securemath/math.asmx> with a valid URL.
mathservice.Url = @"<https://wsserver/securemath/math.asmx>";
mathservice.ClientCertificates.Add(cert);
long lngResult = 0;
try
{
lngResult = mathservice.Add(Int32.Parse(operand1.Text),
Int32.Parse(operand2.Text));
result.Text = lngResult.ToString();
}
catch(Exception ex)
{
if(ex is WebException)
{
WebException we = ex as WebException;
WebResponse webResponse = we.Response;
throw new Exception("Exception calling method. " + ex.Message);
}
}
参考
有关 System.Security.Cryptography.X509Certificates.X509Certificate 类的更多信息,请访问下面的 Microsoft Developer Network (MSDN) 网站:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecuritycryptographyx509certificatesx509certificateclasstopic.asp (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecuritycryptographyx509certificatesx509certificateclasstopic.asp)
有关如何使用 ASP.NET Web 应用程序调用安全性增强的网站的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
817854 (http://support.microsoft.com/kb/817854/) FIX:ASP.NET Web 应用程序不能向安全的 Web 站点传送客户端证书