c# .net

c# - Webclient/HttpWebRequest con Autenticación básica devuelve 404 no encontrado para URL válida



.net (4)

Editar: Quería volver a notar que el problema no estaba en mi extremo, sino con el código del otro lado de la compañía.

Estoy intentando abrir una página usando la Autenticación básica. Sigo recibiendo un error de página 404 no encontrada. Puedo copiar y pegar mi url en el navegador y funciona bien (si no estoy conectado a su sitio ya aparece un cuadro de credenciales, de lo contrario, abre lo que quiero que se abra). Debo estar llegando al lugar correcto y autenticando, porque obtengo un 401 (error no autenticado) si puse intencionadamente un nombre de usuario / contraseña incorrectos y recibo un error interno del servidor 500 si lo paso como un parámetro incorrecto en la cadena de consulta . Intenté usar Webclient y HttpWebRequest, lo que llevó al mismo error 404 no encontrado.

Con Webclient:

string url = "MyValidURLwithQueryString"; WebClient client = new WebClient(); String userName = "myusername"; String passWord = "mypassword"; string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(userName + ":" + passWord)); client.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials; var result = client.DownloadString(url); Response.Write(result);

Con HttpWebRequest

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("MyValidURL"); string authInfo = "username:password"; authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)); request.Headers.Add("Authorization", "Basic " + authInfo); request.Credentials = new NetworkCredential("username", "password"); request.Method = WebRequestMethods.Http.Get; request.AllowAutoRedirect = true; request.Proxy = null; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream stream = response.GetResponseStream(); StreamReader streamreader = new StreamReader(stream); string s = streamreader.ReadToEnd(); Response.Write(s);


Esta parte del código funcionó bien para mí:

WebRequest request = WebRequest.Create(url); request.Method = WebRequestMethods.Http.Get; NetworkCredential networkCredential = new NetworkCredential(logon, password); // logon in format "domain/username" CredentialCache myCredentialCache = new CredentialCache {{new Uri(url), "Basic", networkCredential}}; request.PreAuthenticate = true; request.Credentials = myCredentialCache; using (WebResponse response = request.GetResponse()) { Console.WriteLine(((HttpWebResponse)response).StatusDescription); using (Stream dataStream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(dataStream)) { string responseFromServer = reader.ReadToEnd(); Console.WriteLine(responseFromServer); } } }


Intente cambiar la parte de autenticación de solicitud de cliente web a:

NetworkCredential myCreds = new NetworkCredential(userName, passWord); client.Credentials = myCreds;

Luego haga su llamada, parece funcionar bien para mí.


Si está funcionando cuando está utilizando un navegador y luego transfiere su nombre de usuario y contraseña por primera vez, significa que una vez que se completa la autenticación, el encabezado de Solicitud de su navegador se configura con los valores de autenticación requeridos, que luego se transmiten cada vez que la solicitud se realiza al servidor de alojamiento.

Así que comience por inspeccionar el Encabezado de solicitud (esto podría hacerse usando las herramientas de Desarrolladores web), una vez que haya establecido lo que se requiere en el encabezado, puede pasarlo dentro de su Encabezado de HttpWebRequest.

Ejemplo con Autenticación implícita:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Security.Cryptography; using System.Text.RegularExpressions; using System.Net; using System.IO; namespace NUI { public class DigestAuthFixer { private static string _host; private static string _user; private static string _password; private static string _realm; private static string _nonce; private static string _qop; private static string _cnonce; private static DateTime _cnonceDate; private static int _nc; public DigestAuthFixer(string host, string user, string password) { // TODO: Complete member initialization _host = host; _user = user; _password = password; } private string CalculateMd5Hash( string input) { var inputBytes = Encoding.ASCII.GetBytes(input); var hash = MD5.Create().ComputeHash(inputBytes); var sb = new StringBuilder(); foreach (var b in hash) sb.Append(b.ToString("x2")); return sb.ToString(); } private string GrabHeaderVar( string varName, string header) { var regHeader = new Regex(string.Format(@"{0}=""([^""]*)""", varName)); var matchHeader = regHeader.Match(header); if (matchHeader.Success) return matchHeader.Groups[1].Value; throw new ApplicationException(string.Format("Header {0} not found", varName)); } private string GetDigestHeader( string dir) { _nc = _nc + 1; var ha1 = CalculateMd5Hash(string.Format("{0}:{1}:{2}", _user, _realm, _password)); var ha2 = CalculateMd5Hash(string.Format("{0}:{1}", "GET", dir)); var digestResponse = CalculateMd5Hash(string.Format("{0}:{1}:{2:00000000}:{3}:{4}:{5}", ha1, _nonce, _nc, _cnonce, _qop, ha2)); return string.Format("Digest username=/"{0}/", realm=/"{1}/", nonce=/"{2}/", uri=/"{3}/", " + "algorithm=MD5, response=/"{4}/", qop={5}, nc={6:00000000}, cnonce=/"{7}/"", _user, _realm, _nonce, dir, digestResponse, _qop, _nc, _cnonce); } public string GrabResponse( string dir) { var url = _host + dir; var uri = new Uri(url); var request = (HttpWebRequest)WebRequest.Create(uri); // If we''ve got a recent Auth header, re-use it! if (!string.IsNullOrEmpty(_cnonce) && DateTime.Now.Subtract(_cnonceDate).TotalHours < 1.0) { request.Headers.Add("Authorization", GetDigestHeader(dir)); } HttpWebResponse response; try { response = (HttpWebResponse)request.GetResponse(); } catch (WebException ex) { // Try to fix a 401 exception by adding a Authorization header if (ex.Response == null || ((HttpWebResponse)ex.Response).StatusCode != HttpStatusCode.Unauthorized) throw; var wwwAuthenticateHeader = ex.Response.Headers["WWW-Authenticate"]; _realm = GrabHeaderVar("realm", wwwAuthenticateHeader); _nonce = GrabHeaderVar("nonce", wwwAuthenticateHeader); _qop = GrabHeaderVar("qop", wwwAuthenticateHeader); _nc = 0; _cnonce = new Random().Next(123400, 9999999).ToString(); _cnonceDate = DateTime.Now; var request2 = (HttpWebRequest)WebRequest.Create(uri); request2.Headers.Add("Authorization", GetDigestHeader(dir)); response = (HttpWebResponse)request2.GetResponse(); } var reader = new StreamReader(response.GetResponseStream()); return reader.ReadToEnd(); }

}

Entonces podrías llamarlo:

DigestAuthFixer digest = new DigestAuthFixer(domain, username, password); string strReturn = digest.GrabResponse(dir);

si Url es: http://xyz.rss.com/folder/rss luego dominio: http://xyz.rss.com (parte del dominio) dir: / carpeta / rss (resto de la URL)

también podría devolverlo como una secuencia y usar el método XmlDocument Load ().


//BEWARE //This works ONLY if the server returns 401 first //The client DOES NOT send credentials on first request //ONLY after a 401 client.Credentials = new NetworkCredential(userName, passWord); //doesnt work //So use THIS instead to send credentials RIGHT AWAY string credentials = Convert.ToBase64String( Encoding.ASCII.GetBytes(userName + ":" + password)); client.Headers[HttpRequestHeader.Authorization] = string.Format( "Basic {0}", credentials);