HTTPS POST من بى إلى C #
-
10-07-2019 - |
سؤال
ولقد جعل وظيفة لطرف ثالث الشبكي رابط للحصول على البيانات procesed وإعادته. وكل ما لدي كمثال هو هذا:
$signature= foo_string;
$data_to_post = json_dictionary;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $base_url);
curl_setopt($ch, CURLOPT_USERPWD, "$user:$password");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER,array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_HTTPHEADER,array("JSON-Signature: $signature"));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_to_post);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
curl_close($ch);
ونحن نعمل مع ASP .NET C # 2.0، لا بد لي من ميناء ذلك، ولكن أنا دائما الحصول على خطأ لا autenticated.
وهنا هو ما أفعله:
HttpWebRequest q = (HttpWebRequest)WebRequest.Create(Host + ":" + Port);
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(new interhanse().AcceptAllCertifications);
q.Method = "POST";
q.Headers.Add("JSON-Signature:" + GetSignature(data));
q.ContentType = "application/json";
q.UseDefaultCredentials = false;
q.Credentials = new NetworkCredential(user,pwd, Host);
byte[] buffer = UTF8Encoding.UTF8.GetBytes(data);
q.ContentLength = data.Length;
Stream oStream = q.GetRequestStream();
StreamWriter oWriter = new StreamWriter(oStream);
oWriter.Write(buffer);
oWriter.Close();
HttpWebResponse reps = q.GetResponse() as HttpWebResponse;
ولقد قرأت جميع الأسئلة SO I يمكن العثور على هذا، ولكن أنا لا أحصل على أي تحسينات. ويرجع الفضل في ذلك مسبقا!
المحلول
حسنا، شيء واحد تفعلونه خطأ وعلى افتراض أن طول في بايت م> هو نفس طول في الأحرف م>. يجب عليك استخدام buffer.Length لطول المحتوى. كنت تتصل أيضا StreamWriter.Write
مع صفيف بايت م>. يجب أن لا تفعل ذلك - يجب عليك فقط استخدام تيار، كما كنت قد فعلت الترميز:
byte[] buffer = Encoding.UTF8.GetBytes(data);
q.ContentLength = buffer.Length;
using (Stream stream = q.GetRequestStream())
{
stream.Write(buffer, 0, buffer.Length);
}
والآن، وهذا لن يحل قضية المصادقة. قد تجد أن PreAuthenticate
مجرد وضع يحل هذه على الرغم من:
q.PreAuthenticate = true;
إذا لم يفلح ذلك، أقترح عليك تشغيل يريشارك وإلقاء نظرة على الاختلافات بين الطلب عن طريق الضفيرة و طلب من .NET.
نصائح أخرى
وأعتقد أنك يجب أن يتم توفير المضيف في المصادقة ...
q.Credentials = new NetworkCredential(user,pwd);
والتي من شأنها أن يكون شيئا مثل:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Host + ":" + Port);
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(new interhanse().AcceptAllCertifications);
request.Method = "POST";
request.Headers.Add("JSON-Signature:" + GetSignature(data));
request.ContentType = "application/json";
request.UseDefaultCredentials = false;
request.Credentials = new NetworkCredential(user, pwd);
byte[] buffer = UTF8Encoding.UTF8.GetBytes(data);
request.ContentLength = buffer.Length;
using (Stream oStream = request.GetRequestStream()) {
oStream.Write(buffer, 0, buffer.Length);
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
// load data from response here
}
وأيضا يجب تجنب تعيين مركز خدمة التحقق من صحة مندوب على كل طلب، وهذا قد تبطئ طلبات متزايدة لأن المصادقة يتم تنفيذ عدة مرات، وانها أيضا نوع من تسرب الذاكرة.
curl_setopt($ch, CURLOPT_USERPWD, "$user:$password");
وهنا هو كيف أضيف أن CURLOPT_USERPWD في Asp.Net:
private async Task<string> Execute(string url, string query, string user, string pasword)
{
HttpClient httpClient = new HttpClient();
var baseUri = new Uri(url, UriKind.Absolute); // e.g. http://somedomain.com/endpoint
Uri request = new Uri(baseUri, query); // with query e.g. http://somedomain.com/endpoint?arg1=xyz&arg2=abc
// Add a new Request Message
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, request);
// add headers -> CURLOPT_USERPWD equivalent
var encodedStr = Convert.ToBase64String(Encoding.Default.GetBytes(string.Format("{0}:{1}", user, password)));
var authorizationKey = "Basic" + " " + encodedStr; // Note: Basic case sensitive
requestMessage.Headers.Add("Authorization", authorizationKey);
// if POST - do this instead
// content
//HttpContent content = new StringContent(jsonContent); // string jsonContent i.e. JsonConvert.SerializeObject(YourObject);
//requestMessage.Content = content;
//requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
// execute
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
var responseString = await responseMessage.Content.ReadAsStringAsync(); // reads it as string;
// if json and you need to convert to an object do this
// var myresponse = JsonConvert.DeserializeObject<YourMappedObject>(responseString);
return responseString;
}