2012-09-14 25 views
6

He intentado crear un servicio RESTful autónomo relativamente sencillo con WCF, pero quería agregar una autenticación personalizada. Para ese fin intenté sobreescribir el UserNamePasswordValidator. Desafortunadamente, a pesar de que esto se llama para validar una combinación de nombre de usuario/contraseña, si el nombre de usuario/contraseña no pasan, el servidor devuelve un 403 Prohibido, en lugar de un 401 no autorizado, como era de esperar. Esto causará un gran problema porque si un usuario no se autentica la primera vez, no se le pedirá que ingrese las credenciales nuevamente a menos que reinicie el navegador. Entonces, ¿qué estoy haciendo mal?¿Por qué mi servicio WCF alojado automáticamente devuelve 403 Prohibido, en lugar de 401 No autorizado?

Esto es lo que tengo hasta ahora:

(El actual ServiceContract contiene un único método que devuelve una cadena)

class Program 
{ 
    static void Main(string[] args) 
    { 
     WebServiceHost host = null; 
     try 
     { 
      host = new WebServiceHost(typeof (MyService)); 
      const string uri = "http://127.0.0.1/MyService"; 
      var wb = new WebHttpBinding 
          { 
           Security = 
            { 
             Mode = WebHttpSecurityMode.TransportCredentialOnly, 
             Transport = {ClientCredentialType = HttpClientCredentialType.Basic} 
            } 
          }; 
      var ep = host.AddServiceEndpoint(typeof (IMyService), wb, uri); 
      host.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom; 
      host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new PasswordValidator(); 
      host.Open(); 

      Console.WriteLine("Press any key to terminate"); 
      Console.ReadKey(); 
     } 
     finally 
     { 
      if (host != null) host.Close(); 
     } 
    } 
} 

public class PasswordValidator : UserNamePasswordValidator 
{ 
    public override void Validate(string userName, string password) 
    { 
     if (null == userName || null == password) 
      throw new ArgumentNullException(); 

     if (userName == "Test" && password == "Password") return; 
     throw new WebFaultException(HttpStatusCode.Unauthorized); 
    } 
} 

yo ya he tomado nota de esta other, similar question, pero ninguno de los las respuestas publicadas allí realmente funcionan. Espero que una versión más definida de la pregunta genere algunas respuestas mejores.

+1

Esto podría ayudar a http://stackoverflow.com/questions/2198560/self-hosted-wcf-rest-service-and-basic-authentication – Alex

+0

No ayuda exactamente, como tal, pero proporciona soporte moral y explicación :) – adhocgeek

+0

En realidad, retiro eso, no había leído lo suficiente como para ver que hay una solución allí, idéntica a la publicada y aceptada en esta pregunta. – adhocgeek

Respuesta

7

Prueba esto:

public override void Validate(string userName, string password) 
{ 
    if (null == userName || null == password)    
     throw new ArgumentNullException(); 
    if (userName == "Test" || password == "Password") return; 

    WebFaultException rejectEx = new WebFaultException(HttpStatusCode.Unauthorized); 
    rejectEx.Data.Add("HttpStatusCode", rejectEx.StatusCode); 
    throw rejectEx; 
} 

Por lo que yo sé que esto es una técnica indocumentado que se basa en la forma en la pila de WCF maneja excepciones internamente. Debería haber una manera documentada pero no he encontrado ninguna.

+0

¿Dónde descubriste esto? :) Funciona, pero me hace pensar si realmente quiero usar WCF ahora ... – adhocgeek

+0

Miré el código WCF usando Reflector. –

Cuestiones relacionadas