.NET https requests with different security protocols across threads

前端 未结 2 1788
余生分开走
余生分开走 2020-12-08 16:06

I maintain a quite complex ASP.NET application (a customized NopCommerce 3.10). It needs to connect to third-party servers through HTTPS on different scenarios. I am doing t

相关标签:
2条回答
  • 2020-12-08 16:37

    You could simply use the callback you mentioned (ServicePointManager.ServerCertificateValidationCallback) to implement a custom validation logic: you bypass the errors only if they come from that malicious server.

    0 讨论(0)
  • 2020-12-08 16:55

    We faced this same issue, and went for the app-domain approach you mentioned, implementing a solution based on what is proposed here, which is a really nice write up of how to manage the execution of code in a separate app domain:

    http://www.superstarcoders.com/blogs/posts/executing-code-in-a-separate-application-domain-using-c-sharp.aspx

    We are using his Isolated class pretty much as is:

      public sealed class Isolated<T> : IDisposable where T : MarshalByRefObject
      {
        private AppDomain _domain;
        private readonly T _value;
    
        public Isolated()
        {
            _domain = AppDomain.CreateDomain("Isolated:" + Guid.NewGuid(), null, AppDomain.CurrentDomain.SetupInformation);
    
            var type = typeof(T);
    
            _value = (T)_domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
        }
    
        public T Value
        {
            get
            {
                return _value;
            }
        }
    
        public void Dispose()
        {
            if (_domain == null) return;
    
            AppDomain.Unload(_domain);
    
            _domain = null;
        }
    }
    

    And then we have a wrapper around the standard WebClient, that allows for the setting of the protocol:

    public class WebClient : MarshalByRefObject, IWebClient
    {
        public WebClientResponse GetResponse(string address)
        {
            return GetResponse(address, null);
        }
    
        public WebClientResponse GetResponse(string address, string securityProtocol)
        {
            if (!string.IsNullOrWhiteSpace(securityProtocol))
                ServicePointManager.SecurityProtocol = (SecurityProtocolType)Enum.Parse(typeof(SecurityProtocolType), securityProtocol);
    
            var response = new WebClientResponse();
    
            try
            {
                using (var wc = new System.Net.WebClient())
                {
                  // <do stuff>
                }
            }
            catch (Exception ex)
            {
                response.Exception = new GetResponseException(string.Format("Unable to get response from {0}", address), ex);
            }
    
            return response;
        }
    }
    
    [Serializable]
    public class WebClientResponse
    {
        public Exception Exception { get; set; }
    
        public string Response { get; set; }
    }
    
     [Serializable]
    public class GetResponseException : Exception
    {
        public GetResponseException(string message, Exception innerException)
            : base(message, innerException)
        {
        }
    
        public GetResponseException(SerializationInfo info, StreamingContext context)  : base(info, context)
        {
        }
    }
    

    Tying them together, we have code that determines if it needs to override the protocol that's currently set. If so, it spins up the isolated app domain, if not it uses an existing WebClient:

    ...
            WebClientResponse webClientResponse;
    
            if (!string.IsNullOrWhiteSpace(ForceSecurityProtocol))
            {
                using (var isolated = new Isolated<WebClient>())
                {
                    webClientResponse = isolated.Value.GetResponse(url, ForceSecurityProtocol);
                }
            }
            else
            {
                webClientResponse = _webClient.GetResponse(url);
            }
    ...
    

    Note, our use isn't in a tremendously high throughput area of our application, so whatever performance price we're paying using this approach is really non-impactful. If we were going to put something like this in a place where it been in the way of a significant amount of traffic through our web app, we would have done some testing.

    0 讨论(0)
提交回复
热议问题