HttpWebRequest usando autenticación básica

138

Estoy tratando de pasar por una solicitud de autenticación que imita la "solicitud de autenticación básica" que estamos acostumbrados a ver al configurar IIS para este comportamiento.

La URL es: https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2
(advertencia: https!)

Este servidor se ejecuta bajo UNIX y Java como servidor de aplicaciones.

Este es el código que uso para conectarme a este servidor:

CookieContainer myContainer = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2");
request.Credentials = new NetworkCredential(xxx,xxx);
request.CookieContainer = myContainer;
request.PreAuthenticate = true;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

(Copié esto de otra publicación en este sitio). Pero recibo esta respuesta del servidor:

La conexión subyacente se cerró: se produjo un error inesperado en un envío.

Creo que probé todas las tareas posibles que me ofrece mi conocimiento sobre C #, pero nada ...

Kenny Rullo
fuente
Creo que este habría funcionado si hubiera agregado: request.UseDefaultCredentials = false;
bpeikes

Respuestas:

274

También puede agregar el encabezado de autorización usted mismo.

Simplemente escriba el nombre "Autorización" y el valor "BASE64 básico ({NOMBRE DE USUARIO: CONTRASEÑA})"

String username = "abc";
String password = "123";
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
httpWebRequest.Headers.Add("Authorization", "Basic " + encoded);

Editar

Cambió la codificación de UTF-8 a ISO 8859-1 por ¿Qué codificación debo usar para la autenticación básica HTTP? y el comentario de Jeroen.

Zambonilli
fuente
3
Entonces, ¿cómo saber con certeza que UTF8 es la codificación correcta para usar?
Jeroen Wiert Pluimers
2
Buena atrapada. Parece que el encabezado de autenticación de solicitud debe estar codificado en ISO-8859-1. Por stackoverflow.com/questions/7242316/…
Zambonilli
1
Aaaargh! 1: Gracias amigo. 2. Realmente me gustaría entender por qué los otros métodos, establecer el método de autenticación en CredentialCache, no funcionarían en absoluto. Se supone que deben hacerlo, ¿no es así?
mshthn
1
Toda la documentación de msdn apunta a sí, los otros métodos deberían funcionar. Sin embargo, nunca he podido hacer que trabajen.
Zambonilli
No funciona para mí (ni utf-8 ni ISO-8859-1). ¿Alguna sugerencia de qué verificar? Funciona cuando hago "webRequest.Credentials = new NetworkCredential (UserID, Password);" .
RollerCosta
56

¡Finalmente lo entendí!

string url = @"https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2";
WebRequest request = WebRequest.Create(url);
request.Credentials = GetCredential();
request.PreAuthenticate = true;

y esto es GetCredential()

private CredentialCache GetCredential()
{
    string url = @"https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2";
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
    CredentialCache credentialCache = new CredentialCache();
    credentialCache.Add(new System.Uri(url), "Basic", new NetworkCredential(ConfigurationManager.AppSettings["ead_username"], ConfigurationManager.AppSettings["ead_password"]));
    return credentialCache;
}

¡HURRA!

Kenny Rullo
fuente
29

Si puede usar la WebClientclase, usar la autenticación básica se vuelve simple:

var client = new WebClient {Credentials = new NetworkCredential("user_name", "password")};
var response = client.DownloadString("https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2");
Tamir
fuente
8

Prueba esto:

System.Net.CredentialCache credentialCache = new System.Net.CredentialCache(); 
credentialCache.Add(
    new System.Uri("http://www.yoururl.com/"),
    "Basic", 
    new System.Net.NetworkCredential("username", "password")
);

...
...

httpWebRequest.Credentials = credentialCache; 
MrEyes
fuente
¿Es definitivamente una autenticación básica? Además, ¿puede acceder al recurso con su nombre de usuario / contraseña a través de un navegador?
MrEyes
Parece ser una autenticación básica sobre https. Si hace clic en el enlace que proporcioné, el navegador muestra la solicitud de nombre de usuario / contraseña "de la misma manera que cuando hace" autenticación básica "en IIS o usa un archivo .htaccss en una carpeta a través de Apache. Intenté usar el violinista pero No tengo ni idea.
Kenny Rullo
Me acabo de enterar de que el sitio web se ejecuta bajo el servidor http de IBM. ¿Esto puede ser una noticia útil?
Kenny Rullo
5

Para aquellos que usan RestSharp , puede fallar cuando se usa SimpleAuthenticator (posiblemente debido a que no se usa ISO-8859-1 detrás de escena). Logré hacerlo enviando explícitamente los encabezados de autenticación básica:

string username = "...";
string password = "...";

public IRestResponse GetResponse(string url, Method method = Method.GET)
{
    string encoded = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes($"{username}:{password}"));
    var client = new RestClient(url);
    var request = new RestRequest(method );
    request.AddHeader("Authorization", $"Basic {encoded}");
    IRestResponse response = client.Execute(request);
    return response;
}

var response = GetResponse(url);
txtResult.Text = response.Content;
Alexei
fuente
3

El siguiente código resolverá la respuesta de json si se implementa la autenticación básica y el proxy. También se resolverá el problema de alojamiento IIS 7.5.

public string HttpGetByWebRequ(string uri, string username, string password)
{
//For Basic Authentication
    string authInfo = username + ":" + password;
    authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));

//For Proxy
    WebProxy proxy = new WebProxy("http://10.127.0.1:8080", true);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "GET";
    request.Accept = "application/json; charset=utf-8";
    request.Proxy = proxy;

    request.Headers["Authorization"] = "Basic " + authInfo;

    var response = (HttpWebResponse)request.GetResponse();

    string strResponse = "";
    using (var sr = new StreamReader(response.GetResponseStream()))
    {
        strResponse= sr.ReadToEnd();

    }

    return strResponse;
}
Mahabubuzzaman
fuente
No funciona para mí (ni utf-8 ni ISO-8859-1 ni predeterminado). ¿Alguna sugerencia para verificar? Tenga en cuenta: funciona cuando hago "webRequest.Credentials = new NetworkCredential (UserID, Password);"
RollerCosta
1

La siguiente construcción no funcionaba correctamente para mí:

request.Credentials = new NetworkCredential("user", "pass");

He usado en su CredentialCachelugar:

CredentialCache credentialCache = new CredentialCache
{
    {
        new Uri($"http://{request.Host}/"), "Basic",
        new NetworkCredential("user", "pass")
    }
};
request.Credentials = credentialCache;

Sin embargo, si desea agregar múltiples credenciales de autenticación básicas (por ejemplo, si conoce la redirección), puede usar la siguiente función que he realizado:

private void SetNetworkCredential(Uri uriPrefix, string authType, NetworkCredential credential)
{
    if (request.Credentials == null)
    {
        request.Credentials = new CredentialCache();
    }

    if (request.Credentials.GetCredential(uriPrefix, authType) == null)
    {
        (request.Credentials as CredentialCache).Add(uriPrefix, authType, credential);
    }
}

Espero que ayude a alguien en el futuro.

Gucu112
fuente
0

Lo primero, para mí ServicePointManager.SecurityProtocol = SecurityProtocolType. Tls12 funcionó en lugar de Ssl3.

En segundo lugar, tuve que enviar la solicitud de autenticación básica junto con algunos datos (formulario urlencoded). Aquí está la muestra completa que funcionó perfectamente para mí, después de probar muchas soluciones.

Descargo de responsabilidad: el siguiente código es una mezcla de soluciones que se encuentran en este enlace y algunos otros enlaces de stackoverflow, gracias por la información útil.

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        String username = "user_name";
        String password = "password";
        String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));

        //Form Data
        var formData = "var1=val1&var2=val2";
        var encodedFormData = Encoding.ASCII.GetBytes(formData);

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("THE_URL");
        request.ContentType = "application/x-www-form-urlencoded";
        request.Method = "POST";
        request.ContentLength = encodedFormData.Length;
        request.Headers.Add("Authorization", "Basic " + encoded);
        request.PreAuthenticate = true;

        using (var stream = request.GetRequestStream())
        {
            stream.Write(encodedFormData, 0, encodedFormData.Length);
        }

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
Jiten
fuente