43

Web APIを使用したASP.NET MVC 4プロジェクトがあります。コントローラでは、[Authorize]属性を使用して権限を要求するようにクラスを設定しました。認証のために私はASP.NET Membership Providerを使用していて、Web.Configを "Forms"認証を使用するように設定しています。ASP.NET MVC 4 Web APIのメンバーシッププロバイダによる認証

APIのテストを終えて[許可]属性でコントローラを保護する必要があるまで、すべてがうまく機能しています。メンバーシッププロバイダー。だから私はバイオリンを起動し、認証を追加することと同じ呼び出しますので、同じように私の会員プロバイダからパスワード:

enter image description here

私は401不正であり、「認証」の下に入る応答ユーザ名と一緒に基本的な属性を私は "いいえWWW - 認証ヘッダーが存在する"を取得します。次に、APIがSHA1でエンコードされたキーを探していることに気付きました。だから私は、検索からSHA1発電機を起動し、自分のユーザー名のハッシュを取得:パスワードなどのように、私のリクエスト・ヘッダーを更新:

enter image description here

これはどちらか動作しないと私は同じ結果を得ます。また、私は明らかに私のユーザ名/パスワードを解読するためにサーバと一緒に使用するために、ある種の「共有秘密鍵」が必要です。

だから私の質問:私は、サーバーからこのキーを取得するにはどうすればよい

  1. (またはこの場合は仮想IISにVS 2012をオフに実行しています)。
  2. ASP.NETメンバーシッププロバイダからのユーザー名/パスワードを使用して、Fiddlerで認証済みの呼び出しを行うにはどうすればよいですか。
  3. クライアントアプリケーションで同じ呼び出し(C#WPF App)を使用するにはどうすればよいでしょうか。
  4. HTTPコールでSSLと組み合わされたときに最も効果的ですか?何ではない場合は?

ありがとうございます!

答えて

67

SSLでbasic authenticationを使用できます。サーバー側では、我々は、登録memebershipプロバイダに問い合わせることによって、資格情報を確認し、有効な場合は、ロールを取得し、現在のプリンシパルを設定しますハンドラを委任するカスタムを書くことができ:

public class BasicAuthenticationMessageHandler : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     var authHeader = request.Headers.Authorization; 

     if (authHeader == null) 
     { 
      return base.SendAsync(request, cancellationToken); 
     } 

     if (authHeader.Scheme != "Basic") 
     { 
      return base.SendAsync(request, cancellationToken); 
     } 

     var encodedUserPass = authHeader.Parameter.Trim(); 
     var userPass = Encoding.ASCII.GetString(Convert.FromBase64String(encodedUserPass)); 
     var parts = userPass.Split(":".ToCharArray()); 
     var username = parts[0]; 
     var password = parts[1]; 

     if (!Membership.ValidateUser(username, password)) 
     { 
      return base.SendAsync(request, cancellationToken); 
     } 

     var identity = new GenericIdentity(username, "Basic"); 
     string[] roles = Roles.Provider.GetRolesForUser(username); 
     var principal = new GenericPrincipal(identity, roles); 
     Thread.CurrentPrincipal = principal; 
     if (HttpContext.Current != null) 
     { 
      HttpContext.Current.User = principal; 
     } 

     return base.SendAsync(request, cancellationToken); 
    } 
} 

私たちは、このハンドラを登録しますApplication_Startに:

GlobalConfiguration.Configuration.MessageHandlers.Add(
    new BasicAuthenticationMessageHandler() 
); 

今、私たちは、認証されたユーザーのみがそのアクションにアクセスできることを確実にするために、[承認]属性で修飾されたAPIコントローラを持つことができます:

[Authorize] 
public class ValuesController : ApiController 
{ 
    public string Get() 
    { 
     return string.Format("Hello {0}", User.Identity.Name); 
    } 
} 

さてさて、今のは、サンプルのクライアントを見てみましょう:

using System; 
using System.Net; 
using System.Net.Http; 
using System.Net.Http.Headers; 
using System.Text; 

class Program 
{ 
    static void Main() 
    { 
     // since for testing purposes I am using IIS Express 
     // with an invalid SSL certificate I need to desactivate 
     // the check for this certificate. 
     ServicePointManager.ServerCertificateValidationCallback += 
      (sender, certificate, chain, sslPolicyErrors) => true; 

     using (var client = new HttpClient()) 
     { 
      var buffer = Encoding.ASCII.GetBytes("john:secret"); 
      var authHeader = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(buffer)); 
      client.DefaultRequestHeaders.Authorization = authHeader; 
      var task = client.GetAsync("https://localhost:44300/api/values"); 
      if (task.Result.StatusCode == HttpStatusCode.Unauthorized) 
      { 
       Console.WriteLine("wrong credentials"); 
      } 
      else 
      { 
       task.Result.EnsureSuccessStatusCode(); 
       Console.WriteLine(task.Result.Content.ReadAsAsync<string>().Result); 
      } 
     } 
    } 
} 
+0

おかげダーリンが、これは私が必要なものを正確です! – CodeAbundance

+0

コントローラメソッドの 'User.Identity.Name'は私にとっては空です。' User.Identity.IsAuthenticated'は 'false'です。デバッガで、 'Thread.CurrentPrincipal'がメッセージハンドラ内の正しいユーザ名とロールでプリンシパルに設定されているのがわかります。また、 '[Authorization(Roles = ...)] '属性が尊重されています:間違った役割のユーザーを使用すると、私はUnauthorizedレスポンスを取得し、コントローラーメソッドに到達しません。しかし、 'User.Identity'は私がメッセージハンドラで設定した値を持っていません。何が間違っているのか考えていますか? – Slauma

+0

@Slauma、私はこれを再現することができません。問題を再現する方法を段階的に説明する新しいスレッドを開始することもできます(もちろん、空のプロジェクトから開始することもできます)。 –

関連する問題