2012-09-14 14 views
6

Ich habe versucht, einen relativ einfachen, selbst gehosteten RESTful-Service mit WCF zu erstellen, aber ich wollte eine benutzerdefinierte Authentifizierung hinzufügen. Zu diesem Zweck habe ich versucht, die UserNamePasswordValidator zu überschreiben. Leider, obwohl dies aufgerufen wird, um eine Benutzername/Passwort-Kombination zu validieren, gibt der Server, wenn der Benutzername/das Passwort nicht besteht, einen 403 Forbidden statt 401 Unauthorized zurück, wie ich es erwarten würde. Dies führt zu einem großen Problem, denn wenn ein Benutzer sich beim ersten Mal nicht authentifizieren kann, werden sie nicht aufgefordert, die Anmeldeinformationen erneut einzugeben, es sei denn, sie starten den Browser neu. Also, was mache ich falsch?Warum gibt mein selbst gehosteter WCF-Dienst 403 Forbidden und nicht 401 Unauthorized zurück?

Dies ist, was ich bisher:

(Die tatsächliche ServiceContract eine einzige Methode enthält, die einen String zurückgibt)

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); 
    } 
} 

ich bereits gemacht habe Kenntnis von diesem other, similar question, aber keiner von der Dort gepostete Antworten funktionieren. Ich hoffe, dass eine vollständigere Version der Frage einige bessere Antworten hervorruft.

+1

Dies könnte helfen http://stackoverflow.com/questions/2198560/self-hosted-wcf-rest-service-and-basic-authentication – Alex

+0

Es hilft nicht genau als solches, aber es bietet moralische Unterstützung und Erklärung :) – adhocgeek

+0

Eigentlich nehme ich das zurück, ich hatte nicht weit genug gelesen, um zu sehen, dass es dort eine Lösung gibt, die identisch ist mit der, die in dieser Frage gepostet und akzeptiert wurde. – adhocgeek

Antwort

7

Versuchen Sie folgendes:

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; 
} 

Soweit ich weiß, dass dies eine nicht dokumentierte Technik, die auf beruht, wie die WCF-Stack Ausnahmen intern verwaltet. Es sollte einen dokumentierten Weg geben, aber ich habe keinen gefunden.

+0

Wo hast du das entdeckt? :) Es funktioniert, aber es hat mich darüber nachdenken, ob ich jetzt WCF wirklich verwenden möchte ... – adhocgeek

+0

Ich schaute auf den WCF-Code mit Reflector. –

Verwandte Themen