SSL原理及应用(3).NET开发中处理HTTPS
在ASP.NET、SQL Server、WCF等通信领域,微软都提供了基于SSL的安全保护机制。遗憾的是,.NET并没有对SSL协议本身提供像TCP、UDP这样的基础网络协议的编程性支持。如果想从协议的角度处理SSL通信或者想构建完整的SSL框架,那么.NET帮不上你,但是还有选择,许多第三方安全通信的项目提供了支持,比如OpenSSL。这不意味着我们在此领域将无所作为,第6章介绍了.NET中操作数字证书的两个类:
q System.Security.Cryptography.X509Certificates.X509Certificate2类
q System.Security.Cryptography.X509Certificates.X509Store类
在Web开发中,SSL通信由浏览器和Web服务器来实现通信细节。封装了HTTP协议的WebRequest、WebResponse等类提供了处理HTTPS请求的能力。当我们在程序中向HTTPS链接发送请求的时候,可以获取服务器返回的证书。
请求HTTPS链接
当使用WebRequest类请求HTTPS链接的时候,在操作上和请求普通的HTTP链接没什么不同。代码清单8-1演示了如何获取一个HTTPS链接的方法。
代码清单 8-1获取HTTPS链接
try
{
Uri uri = new Uri("https://www.sample.com/https.aspx");
WebRequest http = HttpWebRequest.Create(uri);
HttpWebResponse response = (HttpWebResponse)http.GetResponse();
Stream stream = response.GetResponseStream();
}
catch(UriFormatException e)
{
Console.WriteLine("无效的URL");
}
catch(IOException e)
{
Console.WriteLine("连接失败");
}
代码清单8-1中,通过HttpWebRequest对象的Create方法创建一个简单的HTTPS请求,并反回一个HttpWebResponse对象。
说明 HttpWebRequest类对WebRequest中定义的属性和方法提供支持,在使用HttpWebRequest对象向HTTP服务器发起请求时请不要使用HttpWebRequest对象的构造函数,而应该使用WebRequest.Create()方法来初始化新的HttpWebRequest对象。如果统一资源标识符方案是"http://"或"https://"时,Create()则返回HttpWebResponse对象。
证书信息的获取与证书加载
在代码清单8-1的基础上,只需略加修改就可以让程序适应需要提交客户端证书的情况。如代码清单8-2所示。
码清单8-2 证书信息的获取与证书加载
public void Test()
{
Uri uri = new Uri("https://www.sample.com/https.aspx");
HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
X509Certificate cer = X509Certificate.CreateFromCertFile("证书文件地址");
httpRequest.ClientCertificates.Add(cer);
HttpWebResponse response = (HttpWebResponse)httpRequest.GetResponse();
Stream stream = response.GetResponseStream();
}
在代码清单8-2中,首先创建一个X509Certificate对象,把它添加到WebRequest的ClientCertificates集合中。我们的证书一定要保护密钥信息。
在服务器端,可以从客户端请求的上下文中获取客户端提交的证书。
在Asp.NET中,可以通过下面的代码来获取证书信息:
Request.ClientCertificate(key[SubField])
在上面的代码中,Key指定要获取证书字段的名称,不同的Key值具有不同的含义,SubField为可选字段。Key具体信息如表8-2所示。
表8-2 Request.ClientCertificate的Key值信息
值 |
意义 |
Certificate |
ASN.1 格式的二进制流字符串,即完整的证书内容 |
Flags |
一组标志,提供其他客户端证书信息。可以设置:ceCertPresent(当前的客户端证书)和ceUnrecognizedIssuer(该链接上来自未知的发行者的最后一个证书) |
Issuer |
包含子字段值的列表的字符串,此列表包含证书颁发者的信息。若该值在无SubField项的情况下指定,则ClientCertificate集合返回一个以逗号分隔的子字段列表。例如:C=US, O=Verisign等 |
SerialNumber |
包含证书的序列号的字符串,序列号以连字符(-)分隔的16进制ASCII码表示,如04-67-F3-02 |
Subject |
包含子字段值的列表的字符串,此列表包含有关证书的主题信息。若该值在无SubField项的情况下指定,则 ClientCertificate 集合返回一个以逗号分隔的子字段列表。例如,C=US, O=Verisign等 |
ValidFrom |
指定证书何时有效。此日期遵循VBScript格式并随国家(地区)设置而变化。例如,在美国可表示为9/26/96 11:59:59 PM |
ValidUntil |
指定证书何时到期 |
SubField用于按Subject或Issuer关键字检索单独的字段。此参数作为一个后缀添加到Key参数中,如IssuerO或SubjectCN。表8-3列出了一些通用的SubField值。
表8-3 SubField支持的参数和意义
值 |
意义 |
C |
指定原国家(地区)名 |
CN |
指定公用用户名(此子字段仅同 Subject 关键字一起使用) |
GN |
指定给定的名称 |
L |
指定所在地 |
O |
指定公司或组织名称 |
OU |
指定机构的名称 |
S |
指定州或省 |
T |
指定此人或组织的头衔 |
根据表8-2和表8-3的说明,可以获取关于客户端证书的完整信息,这里不再演示。
----------------------注:本文部分内容改编自《.NET 安全揭秘》