我正在尝试修补.net网络应用程序,经过多年的工作开始未能获得UPS运输报价,这对网络业务产生了巨大影响。经过多次试验和错误,我发现以下代码在控制台应用程序中运行良好:
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()
上抛出异常:
身份验证失败,因为远程方已关闭传输流。
我在应用程序的几个不同位置尝试了相同的结果。
哪些Web应用程序环境会影响请求?
答案 0 :(得分:4)
事实证明这是一个TLS问题。我猜控制台应用程序默认使用比Web应用程序更高的协议,尽管没有指定。因此,您所要做的就是在发出请求之前的某个时间添加以下代码行:
using System.Net;
...
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
尽管我花了大量的时间在那里,但这就完成了所有工作。
以下是UPS对此问题的回复:
自2018年1月18日起,UPS将仅接受TLS 1.1和TLS 1.2安全协议...使用生产URL(在线工具名称)时,来自TLS 1.0客户的100%请求将是拒绝。
无论如何,希望这有助于某人。
吉姆
答案 1 :(得分:0)
您可以尝试将凭据设置为您的请求对象,如下所示。
request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
答案 2 :(得分:0)
尝试设置默认凭据或检查是否设置了任何代理服务器并将其传递,如下例所示。
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;
}