https 请求仅在 .net web 应用程序中失败

https request fails only in .net web app

我正在尝试修补一个 .net Web 应用程序,该应用程序经过多年的工作后开始无法获得 UPS 运输报价,这极大地影响了 Web 业务。经过反复试验,我发现以下代码在控制台应用程序中运行良好:

static string FindUPSPlease()
{
    string post_data = "<xml data string>";
    string uri = "https://onlinetools.ups.com/ups.app/xml/Rate";

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 
    request.Method = "POST";
    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;

    byte[] postBytes = Encoding.ASCII.GetBytes(post_data);

    request.ContentType = "application/x-www-form-urlencoded";
    request.ContentLength = postBytes.Length;
    Stream requestStream = request.GetRequestStream();
    requestStream.Write(postBytes, 0, postBytes.Length);
    requestStream.Close();

    // get response and send to console
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
    Console.WriteLine(response.StatusCode);
    return "done";
}

这在 Visual Studio 中运行得很好,并且从 UPS 得到了一个很好的小响应,即 XML 当然是格式错误的。

但是,如果我在不更改单个字符的情况下将此函数粘贴到 Web 应用程序中,则会在 request.GetRequestStream() 上抛出异常:

Authentication failed because the remote party has closed the transport stream.

我在应用程序的几个不同地方尝试过,结果相同。

Web 应用程序环境有哪些会影响请求?

您能否尝试将凭据设置为您的请求对象,如下所示。

 request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

尝试设置默认凭据或检查是否设置了任何代理服务器并像下面的示例一样传递它。

示例是针对WebClient给出的。

我在设置默认凭据时遇到问题,因为服务器上启用了代理。所以我通过了代理 URL 和带有可以访问它的凭据的端口。

using (System.Net.WebClient web = new System.Net.WebClient())
        {
            //IWebProxy defaultWebProxy = WebRequest.DefaultWebProxy;
            //defaultWebProxy.Credentials = CredentialCache.DefaultCredentials;

            //web.Proxy = defaultWebProxy;

            var proxyURI = new Uri(string.Format("{0}:{1}", proxyURL, proxyPort));

            //Set credentials
            System.Net.ICredentials credentials = new System.Net.NetworkCredential(proxyUserId, proxyPassword);

            //Set proxy
            web.Proxy = new System.Net.WebProxy(proxyURI, true, null, credentials);

            web.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            var result = web.UploadString(URL, "");
            return result;
        }

原来是TLS问题。我猜控制台应用程序默认使用比 Web 应用程序更高的协议,尽管指定了 none。因此,您所要做的就是在发出请求之前的某个时间添加以下代码行:

using System.Net;
...
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

这就是全部,尽管我花了很多时间才到达那里。

以下是 UPS 对此问题的回复:

Effective January 18, 2018, UPS will only accept TLS 1.1 and TLS 1.2 security protocols... 100% of requests from customers who are on TLS 1.0 while using production URLS (onlinetools.ups.com/tool name) will be rejected.

无论如何,希望这对某人有所帮助。

吉姆