c#采用https访问Web服务器的方法

1 基本编程方法:

1 基本编程方法:

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>


<think>好的,我现在需要帮用户解决如何在C#中使用HttpClient访问HTTPS时取消SSL验证的问题。首先,我得回忆一下相关的知识点。用户可能是在开发过程中遇到了SSL证书验证失败的情况,比如使用自签名证书或者测试环境中的证书不被信任,这时候需要绕过验证来继续开发。 首先,我要确定用户的使用场景。通常,取消SSL验证是在测试或开发环境中,生产环境中不建议这样做,因为会降低安全性。所以,我应该提醒用户仅在非生产环境使用该方法,并强调潜在的风险。 接下来,我需要考虑在C#中如何实现取消SSL验证。HttpClient在发送请求时会使用HttpClientHandler来处理底层连接,所以可能需要配置HttpClientHandler的ServerCertificateCustomValidationCallback属性。设置这个回调函数并返回true,应该可以跳过证书验证。 然后,我需要考虑不同的.NET版本之间的差异,比如.NET Core、.NET 5+和旧版.NET Framework可能的区别,是否需要不同的处理方式。同时,还要注意HttpClient的正确用法,避免socket耗尽问题,比如使用单例或静态实例。 另外,用户可能需要代码示例来具体实现,所以应该提供详细的代码片段,包括如何创建HttpClientHandler,设置回调,然后创建HttpClient实例。同时,可能需要解释每个步骤的作用,比如ServerCertificateCustomValidationCallback的作用,BypassCertificateValidation方法的实现等。 还需要提到其他相关注意事项,比如证书固定(Certificate Pinning)可能导致的无法绕过的问题,以及如何全局禁用SSL验证(虽然不推荐,但用户可能有这样的需求),比如使用ServicePointManager的ServerCertificateValidationCallback。不过要注意不同.NET版本的兼容性。 另外,安全性警告非常重要,必须明确告诉用户这样做会暴露中间人攻击的风险,只能在测试环境中使用。可能的话,提供更安全的替代方案,比如正确安装自签名证书到受信任的根证书颁发机构。 在组织回答时,结构要清晰,分步骤说明,可能包括实现步骤、代码示例、注意事项、安全警告等部分。使用用户容易理解的语言,避免过于技术化的术语,但必要时需准确使用专业词汇。 最后,需要验证提供的代码是否正确,确保回调函数正确设置,HttpClientHandler正确传递给HttpClient,并且没有遗漏任何必要的配置步骤。同时,检查是否有拼写错误或语法错误,确保代码可以直接复制使用。</think>以下是取消 HttpClient 的 SSL 证书验证的完整解决方案: --- ### **实现原理** 当访问 HTTPS 站点时,HttpClient 默认会验证 SSL 证书的有效性。要绕过验证,需通过 `HttpClientHandler` 的证书验证回调函数强制返回 `true`(表示接受所有证书)。 --- ### **具体步骤** #### **1. 创建自定义 HttpClientHandler** ```csharp var handler = new HttpClientHandler { // 忽略证书验证 ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true }; ``` #### **2. 创建 HttpClient 实例** ```csharp using var httpClient = new HttpClient(handler); ``` #### **3. 发送请求** ```csharp var response = await httpClient.GetAsync("https://your-insecure-url.com"); ``` --- ### **完整代码示例** ```csharp using System; using System.Net.Http; using System.Threading.Tasks; public class InsecureHttpClientExample { public static async Task SendRequest() { var handler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true }; using var httpClient = new HttpClient(handler); try { var response = await httpClient.GetAsync("https://self-signed-cert-site.com"); response.EnsureSuccessStatusCode(); Console.WriteLine(await response.Content.ReadAsStringAsync()); } catch (Exception ex) { Console.WriteLine($"请求失败: {ex.Message}"); } } } ``` --- ### **关键参数解释** | 参数/属性 | 说明 | |-----------|------| | `ServerCertificateCustomValidationCallback` | 证书验证回调函数,返回 `true` 表示接受所有证书 | | `sslPolicyErrors` | 包含证书错误类型(例如名称不匹配、过期等) | --- ### **高级配置** #### **选择性忽略特定错误** ```csharp ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { // 仅忽略证书过期错误 if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) { return true; } return sslPolicyErrors == System.Net.Security.SslPolicyErrors.None; }; ``` --- ### **重要警告** - ✅ **仅限测试环境使用**:此方法会完全禁用 SSL 验证,使通信面临中间人攻击风险 - ❌ **禁止生产环境使用**:正式部署必须使用有效证书 - 🔧 **替代方案**:将自签名证书安装到系统的受信任根证书颁发机构 --- ### **其他注意事项** 1. **.NET Framework 兼容性**: ```csharp // 旧版 .NET Framework 需使用以下方式 ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; ``` 2. **证书绑定问题**:如果服务器启用了证书绑定(Certificate Pinning),此方法将失效 --- ### **最佳实践建议** ```csharp // 通过环境变量控制安全性 var allowInsecure = Environment.GetEnvironmentVariable("ALLOW_INSECURE_SSL") == "true"; var handler = new HttpClientHandler { ServerCertificateCustomValidationCallback = allowInsecure ? (sender, cert, chain, sslPolicyErrors) => true : HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }; ``` 通过这种方式,您可以在需要时安全地控制 SSL 验证行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值