2012-04-18 13 views
7

.NET(元々はRubyで書かれています)を使用して既存のREST APIを書き直す必要があります。クライアントの観点からは、以前のAPIとまったく同じ方法で動作する必要があります。つまり、クライアントコードを変更する必要はありません。現在のAPIには基本認証が必要です。だから、古いAPIを呼び出すには、次のように完璧に動作します: -ASP.Net Web 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 /ユーザー名/パスワードなどをOMMITしなければなりませんでした)。

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

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

一つのこと、私はコードを配置するのApplication_StartでGlobal.asax.csファイルの「ハンドラ内でフック」()イベント(それは私が推測したので説明しなかった)。

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

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回叩かれることを期待していました。

どのように私はこれを動作させることができますか?

答えて

9

あなたは正しい行動を期待しています。 System.Net.WebClientは、最初の要求時にAuthorizationヘッダーを自動的にインクルードしません。私の知る限りでは、適切なWWW-Authenticateヘッダーであるのステータスコードであるレスポンスによって適切に挑戦されたときだけ、それらを送信します。詳細は、hereおよびhereを参照してください。

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

あなたのハンドラは、このような何かをした場合は、Webクライアントのアプローチの作業目撃必要があります:あなたが気づいたとして、あなたはすべてのリクエストに認証ヘッダを含む場合(あなたは別のアプローチで行ったように)、その後、

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

をあなたのハンドラはすでに動作しています。したがって、WebClientや他のクライアントと同じように動作するのではなく、十分かもしれません。

+0

完璧 - それは働いた!どうもありがとうございました。 – nickthompson

関連する問題