2009-04-20 43 views
6

Tengo un servicio ASMX básico que estoy tratando de ejecutar (prefiero usar WCF pero no puedo hacer que el servidor trabaje con él). Funciona bien en una configuración sin seguridad, pero tan pronto como enciendo la seguridad obtengo:Seguridad de nombre de usuario y contraseña de ASMX

La solicitud HTTP no está autorizada con el esquema de autenticación del cliente 'Anónimo'. El encabezado de autenticación recibido del servidor fue 'Basic realm = "Área protegida"'.

Lo que yo quiero es un minimalista pedir al usuario un nombre y una solución de tipo de contraseña.

Al pulsar el código con intellisense no aparece nada que se parezca a lo que necesito.

This Parece que podría ser útil, pero parece ser WCF, quién sabe.


me he dado cuenta de que puedo hacer de esto una demostración en vivo:

aquí es el servicio: http://smplsite.com/sandbox3/Service1.asmx

el nombre de usuario es testapp y la contraseña es testpw. Necesito una aplicación de línea de comandos que llame a funciones en ese servicio.

Befor añadí seguridad, esta línea trabajaron en un proyecto básico VS después de ejecutar Add Web Service Reference en esa URL

new ServiceReference1.Service1SoapClient().HelloMom("Bob"); 

Este es mi intento actual (que no funciona)

class Program 
{ 
    private static bool customValidation(object s, X509Certificate c, X509Chain ch, SslPolicyErrors e) 
    { return true } 

    static void Main(string[] args) 
    { 
     // accept anything 
     ServicePointManager.ServerCertificateValidationCallback += 
       new RemoteCertificateValidationCallback(customValidation); 

     var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); 
     binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; 
     binding.Security.Transport.Realm = "Secured area"; 

     // the generated Web Service Reference class 
     var client = new ServiceReference1.Service1SoapClient(
      binding, 
      new EndpointAddress("https://smplsite.com/sandbox3/Service1.asmx") 
      ); 

     client.ClientCredentials.UserName.UserName = "testapp"; 
     client.ClientCredentials.UserName.Password = "testpw"; 

     Console.WriteLine(client.HelloMom("Bob")); 
    } 
} 

Edit: BTW esto no es un sitio web o se ejecuta en el navegador, el código de acceso es una aplicación de línea de comandos C#. Además, la autenticación está siendo realizada por otro complemento de IIS que no controlo.

Editar 2: Para ser claro; la solución que estoy buscando es un problema puramente del lado del cliente.

Editar 3: el control de acceso es a través de un .haccess tipo de sistema y me gusta de esa manera. No deseo que el código de servicio realice ninguna autenticación.

+0

Después de leer su edición, no estoy seguro de que mi solución sea útil, ya que el otro complemento de IIS realiza la autenticación. Lo dejaré allí en caso de que encienda una chispa ... – Moose

+0

He editado mi respuesta. No sé si eso ayudará, pero es otro intento ... – Moose

+0

¿puede acceder a su servicio web utilizando un navegador y ver lo que se le envía utilizando el violín? Luego puede intentar duplicar la autenticación que usa el navegador. De lo contrario, me he quedado sin ideas. – Moose

Respuesta

12

Editar:
¿Y si uso esto:

MyWebService svc = new MyWebService();    
svc.Credentials = new System.Net.NetworkCredential(UserID, pwd); 
bool result = svc.MyWebMethod();  

OP dice que esto no funcionaría, y ahora veo que lo haría no en su situación.

hacemos algo como esto:

public class MyWebService : System.Web.Services.WebService 
{ 
    public AuthenticationHeader AuthenticationInformation; 

    public class AuthenticationHeader : SoapHeader 
    { 
     public string UserName; 
     public string Password; 
    } 

    [WebMethod(Description = "Sample WebMethod.")] 
    [SoapHeader("AuthenticationInformation")] 
    public bool MyWebMethod() 
    { 
     if (AuthenticationInformation != null) 
     { 
      if (IsUserAuthenticated(AuthenticationInformation.UserName, 
       AuthenticationInformation.Password, ref errorMessage)) 
      { 
       // Authenticated, do something 
      } 
      else 
      { 
       // Failed Authentication, do something 
      } 
     } 
     else 
     { 
       // No Authentication, do something 
     } 
    } 
} 

Tenga en cuenta que usted suministra IsUserAuthenticated().

A continuación, el cliente llama así:

MyWebService svc = new MyWebService();    
svc.AuthenticationHeaderValue = new MyWebService.AuthenticationHeader(); 
svc.AuthenticationHeaderValue.UserName = UserID; 
svc.AuthenticationHeaderValue.Password = Password; 

bool result = svc.MyWebMethod(); 
+0

No, lo siento, no hace lo que necesito: por lo que puedo decir, IIS rechaza el intento de acceso antes y mi código incluso comienza a ejecutarse. Creo (y espero) que esté usando el mismo tipo de mecanismo que utilizaría para el control de acceso con contenido estático. – BCS

+0

Está bien, entonces, ¿qué pasa con el uso de la Propiedad de credenciales de su objeto de servicio web? – Moose

+0

De hecho estoy haciendo eso, no funciona :( – BCS

2

Voy a añadir una respuesta fresca, porque creo que esto puede ayudar:

http://intellitect.com/calling-web-services-using-basic-authentication/

no voy a duplicar aquí, porque no hice nada más que googlearlo.

+0

Si se llama así, parece lo que quiero ... – BCS

+0

Suena prometedor pero no parece haber un método GetWebRequest para anular :( – BCS

+0

No puedo ver su Servicio web para mirar dentro de sus clases, pero eché un vistazo a uno que uso aquí. Su clase base es System.Web.Services.Protocols.SoapHttpClientProtocol, que tiene una anulación protegida System.Net.WebRequest GetWebRequest (System.Uri uri) . Este es el que necesitaría anular, ¿no? – Moose

0

Config:

<binding name="MyBinding" closeTimeout="00:00:30" 
     openTimeout="00:00:30" receiveTimeout="00:00:30" sendTimeout="00:00:30" 
     allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
     maxBufferPoolSize="524288" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" 
     textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true" 
     messageEncoding="Text"> 
     <readerQuotas maxDepth="32" maxStringContentLength="2147483647" 
     maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
     <security mode="Transport"> 
     <transport clientCredentialType="Basic" realm=""/> 
     </security> 
    </binding> 
    </basicHttpBinding> 

mientras que consume

proxy.ClientCredentials.UserName.UserName = userName; 
proxy.ClientCredentials.UserName.Password = password; 

Esto funcionó muy bien para mí.

Cuestiones relacionadas