6

WCF を使用して、比較的単純なセルフホステッド RESTful サービスを作成しようとしてきましたが、カスタム認証を追加したいと考えていました。そのために、 をオーバーライドしてみましたUserNamePasswordValidator。残念ながら、これはユーザー名とパスワードの組み合わせを検証するために呼び出されていますが、ユーザー名とパスワードが通らない場合、サーバーは 401 Unauthorized ではなく 403 Forbidden を返します。ユーザーが最初の認証に失敗した場合、ブラウザーを再起動しない限り資格情報の再入力を求められないため、これは大きな問題を引き起こします。それで、私は何を間違っていますか?

これは私がこれまでに持っているものです:

(実際ServiceContractには、文字列を返す単一のメソッドが含まれています)

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

私はすでにこの他の同様の質問に注目していますが、そこに投稿された回答はどれも実際には機能しません。質問のより完全に定義されたバージョンが、より良い回答を引き出すことを願っています。

4

1 に答える 1

7

これを試して:

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

私の知る限り、これは文書化されていない手法であり、WCF スタックが内部で例外を管理する方法に依存しています。文書化された方法があるはずですが、見つけられませんでした。

于 2012-09-14T10:38:59.213 に答える