7

.NET (元は Ruby で記述) を使用して既存の REST API を書き直す必要があります。クライアントの観点からは、古い API とまったく同じように動作する必要があります。つまり、クライアント コードを変更する必要はありません。現在の API には基本認証が必要です。したがって、古い API を呼び出すには、次のようにすると完全に機能します。

        var wc = new System.Net.WebClient();
        var myCache = new CredentialCache();
        myCache.Add(new Uri(url), "Basic", new NetworkCredential("XXX", "XXX"));
        wc.Credentials = myCache;
        var returnBytes = wc.DownloadData("http://xxxx");

(セキュリティ上の理由から、実際の URL / ユーザー名 / パスワードなどは省略しなければなりませんでした)。

現在、MVC4 で ASP.Net Web API を使用して新しい API を作成しています。私は奇妙な問題を抱えており、まったく同じ問題を抱えている人を見つけることができません。基本認証をサポートするために、次のガイドラインに従いました。

http://sixgun.wordpress.com/2012/02/29/asp-net-web-api-basic-authentication/

1 つには、Application_Start() イベントの Global.asax.cs ファイルに "ハンドラーにフック" するコードを配置しました (これは説明されていなかったので推測しました)。

とにかく、上記のコードを使用して API (IIS にデプロイしたもの) を呼び出すと、Authorization ヘッダーは常に null になり、上記は 401 Unauthorized で失敗します。ただし、このコードを使用してヘッダーを手動で設定すると、正常に動作します。つまり、Authorization ヘッダーが存在するようになり、ユーザーを認証できます。

    private void SetBasicAuthHeader(WebClient request, String userName, String userPassword)
    {
        string authInfo = userName + ":" + userPassword;
        authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
        request.Headers["Authorization"] = "Basic " + authInfo;
    }
   .......
    var wc = new System.Net.WebClient();
    SetBasicAuthHeader(request, "XXXX", "XXXX");
    var returnBytes = wc.DownloadData("http://xxxx");

それは機能しますが、既存の API の既存のユーザーがヘッダーを手動で設定することはないため、私には良くありません。

基本認証がどのように機能するかを読むと、最初のリクエストは匿名であることが意図されており、クライアントは 401 を返し、クライアントは再試行することを意図しています。ただし、コードにブレークポイントを配置すると、Antony の例ではコードに再びヒットすることはありません。ブレークポイントが 2 回ヒットすることを期待していました。

これを機能させる方法はありますか?

4

1 に答える 1

9

あなたは正しい行動を期待しています。System.Net.WebClient は、最初の要求時に Authorization ヘッダーを自動的に含めません。私の知る限り、401ステータスコードと適切なWWW-Authenticateヘッダーである応答によって適切にチャレンジされた場合にのみ、それらを送信します。詳細については、こちらこちらを参照してください。

基本認証ハンドラーが WWW-Authenticate ヘッダーを返していないため、WebClient は 2 番目の要求で資格情報を送信しようとさえしないと想定しています。これは、Fiddler または同様のツールで確認できるはずです。

ハンドラーがこのようなことをした場合、WebClient アプローチが機能するのを確認する必要があります。

//if is not authenticated or Authorization header is null
return base.SendAsync(request, cancellationToken).ContinueWith(task =>
    {
        var response = task.Result;
        response.StatusCode = HttpStatusCode.Unauthorized;
        response.Headers.Add("WWW-Authenticate", "Basic realm=\"www.whatever.com\"");
        return response;
    });

//else (is authenticated)
return base.SendAsync(request, cancellationToken);

お気づきのように、すべてのリクエストに Authorization ヘッダーを含めると (別のアプローチで行ったように)、ハンドラーは既にそのまま機能します。したがって、それで十分な場合があります。WebClient や、同じように動作する他のクライアントには適していません。

于 2012-04-19T00:22:15.863 に答える