using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Threading;
using Imps.Services.Common;
using Imps.Services.MMSAdapterCommon;
using Imps.Services.MMSAdapter.Common;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public class HttpsRequest
{
public static void Initialize()
{
if(isClientCer)
{
//挂接验证服务端证书的回调
ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidationCallback;
}
}
protected static void ProcessRequest(string uri,string body)
{
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(body);
System.Net.HttpWebRequest webReq = System.Net.HttpWebRequest.Create(url) as HttpWebRequest;
webReq.Method = "POST";
if (isCer)
{
//需要Https验证
System.Security.Cryptography.X509Certificates.X509Certificate cer;
//System.Security.Cryptography.X509Certificates.X509Certificate cer = System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromCertFile(pfxPath);
if (String.IsNullOrEmpty(pfxPassword)) //是否证书加载是否需要密码
cer = new X509Certificate(pfxPath);
else
cer = new X509Certificate(pfxPath, pfxPassword);
webReq.ClientCertificates.Add(cer);
}
webReq.GetRequestStream().Write(buffer, 0, buffer.Length);
webReq.GetRequestStream().Close();
HttpWebResponse response = webReq.GetResponse() as HttpWebResponse;
if (response.StatusCode == HttpStatusCode.OK)
{
}
else
{}
}
public static bool RemoteCertificateValidationCallback(Object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
//如果没有错就表示验证成功
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
else
{
if((SslPolicyErrors.RemoteCertificateNameMismatch & sslPolicyErrors)==SslPolicyErrors.RemoteCertificateNameMismatch)
{
tracing.WarnFmt("证书名称不匹配{0}", sslPolicyErrors);
}
if((SslPolicyErrors.RemoteCertificateChainErrors & sslPolicyErrors)==SslPolicyErrors.RemoteCertificateChainErrors)
{
string msg = "";
foreach (X509ChainStatus status in chain.ChainStatus)
{
msg+="status code ={0} "+status.Status;
msg += "Status info = "+status.StatusInformation+" ";
}
tracing.WarnFmt("证书链错误{0}", msg);
}
tracing.WarnFmt("证书验证失败{0}", sslPolicyErrors);
}
return false;
}
private static string GetStream(System.IO.Stream stream, int contentlen)
{
byte[] buffer = new byte[contentlen];
int len = 1024;
int index = 0;
while ((len = stream.Read(buffer, index, len)) > 0)
{
index = index + len;
}
return System.Text.Encoding.UTF8.GetString(buffer, 0, index);
}
}
2 错误原因查看:
可以添加客户端端回调验证查看具体错误原因,错误原因在sslPolicyErrors 中显示
具体为SslPolicyErrors.RemoteCertificateNameMismatch一般是访问的url名字和证书中的cnname名称不一致
临时解决办法可以在本地host文件中加入
证书域名 访问IP地址
SslPolicyErrors.RemoteCertificateChainErrors 可以在chain.ChainStatus查看具体原因
3 常见问题解释:
3.1 SslPolicyErrors.RemoteCertificateNameMismatch一般是访问的url名字和证书中的cnname名称不一致
临时解决办法可以在本地host文件中加入
证书域名 访问IP地址
3.2 X509ChainStatusFlags.UntrustedRoot
已处理证书链,但是在不受信任提供程序信任的根证书中终止
具体原因为客户端导入的证书不在本地信任列表中。
缺省导入是在本地用户中。
具体导入方法:
运行 -》 certmgr.msc
受信任人---右键----导入证书
另外服务或者web程序,其启动账号最好是安装证书的用户。如果用户没权限也会出现此问题
自己验证用户证书的方法:
using System;
using System.Configuration;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
namespace ClientWeb.CustomX509Validator
{
/// <summary>
/// Implements the validator for X509 certificates.
/// </summary>
public class MyX509Validator: X509CertificateValidator
{
/// <summary>
/// Validates a certificate.
/// </summary>
/// <param name="certificate">The certificate the validate.</param>
public override void Validate(X509Certificate2 certificate)
{
// validate argument
if (certificate == null)
throw new ArgumentNullException("X509认证证书为空!");
// check if the name of the certifcate matches
if (certificate.SubjectName.Name != ConfigurationManager.AppSettings["CertName"])
throw new SecurityTokenValidationException("Certificated was not issued by thrusted issuer");
}
}
}
<behaviors>
<endpointBehaviors>
<behavior name="myClientBehavior">
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="Custom" customCertificateValidatorType="ClientWeb.CustomX509Validator.MyX509Validator,ClientWeb" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
-----------------------------------------------------------------------------
正常情况下,处理https和http没有什么区别,如以下代码,显示了https://www.softlayer.com/的内容
string url = “https://www.softlayer.com/”;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string encoding = response.ContentEncoding;
if (encoding == null || encoding.Length < 1) {
encoding = "UTF-8"; //默认编码
}
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
Console.Write(reader.ReadToEnd());
response.Close();
和http的不同就是地址由http改为了https
但是,如果你将 https://www.softlayer.com/ 改为 https://softlayer.com/,会发现一个异常
未能为 SSL/TLS 安全通道建立信任关系
怎么回事? 用浏览器试一下,访问 https://www.softlayer.com/ 没有问题
访问 https://softlayer.com/ 会有证书问题(虽然是我们自己造成的)
这就对了,如果有证书问题,不做特殊处理,将会抛出异常
怎么处理呢? 如果是dot net 2.0 或以上,加上一个确认函数就可以了,代码如:
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
string url = “https://softlayer.com/”;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string encoding = response.ContentEncoding;
if (encoding == null || encoding.Length < 1) {
encoding = "UTF-8"; //默认编码
}
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
Console.Write(reader.ReadToEnd());
response.Close();
public bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { // Always accept
Console.WriteLine(“accept ” + certificate.GetName());
return true; //总是接受
}
using System.Net;
using System.IO;
using System.Web;
using System.Net.Security;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
如果是dot net 1.1,写法略有不同
ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();
internal class AcceptAllCertificatePolicy : ICertificatePolicy {
public AcceptAllCertificatePolicy() {
}
public bool CheckValidationResult(ServicePoint sPoint, System.Security.Cryptography.X509Certificates.X509Certificate cert, WebRequest wRequest, int certProb) {
// Always accept
return true;
}
}
----------------------------------------------------------------------------------------------------------
我们使用https是,一般都只是服务器提供证书,用于验证服务器的身份
其实ssl是双向的,https有时也需要客户端提供证书,不少对安全性要求高的场合如银行业务就需要。
代码片段示例:HttpWebRequest request;
//blabla
X509Certificate cer = X509Certificate.CreateFromCertFile(“你的cer证书文件”);
request.ClientCertificates.Add(cer);
//blabla