Https POST da Php a C #

Devo fare un post a un https URL di terze parti per get i dati processati e rispediti. E tutto quello che ho come esempio è questo:

$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,arrays('Content-Type: application/json')); curl_setopt($ch, CURLOPT_HTTPHEADER,arrays("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); 

Dato che lavoriamo con ASP .NET C # 2.0, devo eseguire il porting, ma ottengo sempre un errore non autenticato.

Ecco cosa sto facendo:

 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; 

Ho letto tutte le domande SO che posso trovare su questo, ma non ho alcun miglioramento. Grazie in anticipo!

Bene, una cosa che stai facendo male è assumere che la lunghezza in byte sia la stessa della lunghezza in caratteri . Dovresti usare buffer.Lunghezza per la lunghezza del contenuto. Stai anche chiamando StreamWriter.Write con un arrays di byte . Non dovresti farlo – dovresti semplicemente usare lo stream, dato che hai già fatto la codifica:

 byte[] buffer = Encoding.UTF8.GetBytes(data); q.ContentLength = buffer.Length; using (Stream stream = q.GetRequestStream()) { stream.Write(buffer, 0, buffer.Length); } 

Ora, questo non risolverà il problema dell'authentication. Potresti scoprire che l'impostazione di PreAuthenticate risolve il PreAuthenticate :

 q.PreAuthenticate = true; 

Se ciò non funziona, ti suggerisco di eseguire WireShark e osservare le differenze tra la richiesta tramite Curl e la richiesta da .NET.

Penso che non dovresti fornire l'host nell'authentication …

 q.Credentials = new NetworkCredential(user,pwd); 

Quale sarebbe qualcosa di simile:

 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 } 

Inoltre, dovresti evitare di assegnare il delegato di validation del punto di servizio su each richiesta, questo potrebbe rallentare le richieste sempre di più perché la validation viene eseguita più volte, ed è anche una sorta di perdita di memory.

 curl_setopt($ch, CURLOPT_USERPWD, "$user:$password"); 

Ecco come si aggiunge CURLOPT_USERPWD in 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); // eg http://somedomain.com/endpoint Uri request = new Uri(baseUri, query); // with query eg 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 ie 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; }