1

私は、Badri L. によるPro ASP .NET Web API Securityの第 8 章に従っており、HTTP/JS クライアントによって消費される Web アプリケーションに基本認証を実装しようとしています。

次の認証ハンドラーを WebAPI プロジェクトに追加しました。

public class AuthenticationHandler : DelegatingHandler
    {
        private const string SCHEME = "Basic";
        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
                                                                               System.Threading.CancellationToken
                                                                                   cancellationToken)
        {
            try
            {
                // Request Processing
                var headers = request.Headers;
                if (headers.Authorization != null && SCHEME.Equals(headers.Authorization.Scheme))
                {
                    Encoding encoding = Encoding.GetEncoding("iso-8859-1");
                    // etc

API のメソッドを [Authorize] で装飾し、if上記のステートメントにブレークポイントを設定するとheaders.Authorization、最初のリクエストで null になります。この休憩を続けると、if ステートメントが再びヒットします。今回はheaders.Authorization.Scheme、"Basic" ではなく "Negotiate" を使用します。

ここに画像の説明を入力

Handler を WebApiConfig に登録しました。

config.MessageHandlers.Add(new AuthenticationHandler());

しかし、Authorize 属性が基本認証を尊重していない理由、またはその理由について途方に暮れています。スキームが「基本」ではなくif()、ハンドラーが返されるためfalse、必要なときに API コントローラーからデータを取得しています。取得401 Unauthorized

web.config で authenticationType を指定していません。

私が間違っていることは何か分かりますか?

編集:フルハンドラー:

public class AuthenticationHandler : DelegatingHandler
    {
        private const string SCHEME = "Basic";
        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
                                                                               System.Threading.CancellationToken
                                                                                   cancellationToken)
        {
            try
            {
                // Request Processing
                var headers = request.Headers;
                if (headers.Authorization != null && SCHEME.Equals(headers.Authorization.Scheme))
                {
                    Encoding encoding = Encoding.GetEncoding("iso-8859-1");
                    string credentials = encoding.GetString(Convert.FromBase64String(headers.Authorization.Parameter));
                    string[] parts = credentials.Split(':');
                    string userId = parts[0].Trim();
                    string password = parts[1].Trim();
                    // TODO: Authentication of userId and Pasword against credentials store here
                    if (true)
                    {
                        var claims = new List<Claim>
                            {
                                new Claim(ClaimTypes.Name, userId),
                                new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.Password)
                            };
                        var principal = new ClaimsPrincipal(new[] {new ClaimsIdentity(claims, SCHEME)});
                        Thread.CurrentPrincipal = principal;
                        if (HttpContext.Current != null)
                            HttpContext.Current.User = principal;
                    }

                }

                var response = await base.SendAsync(request, cancellationToken);
                // Response processing
                if (response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue(SCHEME));
                }
                return response;
            }
            catch (Exception)
            {
                // Error processing
                var response = request.CreateResponse(HttpStatusCode.Unauthorized);
                response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue(SCHEME));
                return response;
            }
        }

    }
4

3 に答える 3

3

API のメソッドを [Authorize] で装飾し、上記の if ステートメントにブレークポイントを設定すると、最初のリクエストで headers.Authorization が null になります。

これは予期されることです。これが機能するはずの方法です。ブラウザーは、401 を受信した場合にのみ、ユーザーから資格情報を取得するためのポップアップを表示します。その後の要求には、基本スキームの資格情報を含む認証ヘッダーが含まれます。

この休憩を続けると、if ステートメントが再びヒットします。今回は、headers.Authorization.Scheme を「Basic」ではなく「Negotiate」にします。

はい、ドミニクが答えたように(ドミニクですか?)、Windows認証が有効になっているため、ブラウザからネゴシエートスキームが返されます。構成で、または IIS マネージャーを使用して、すべての認証方法を無効にする必要があります。

しかし、Authorize 属性が基本認証を考慮していない理由、またはその理由について途方に暮れています。スキームが「基本」ではなく、ハンドラーの if() が false を返すため、API コントローラーからデータを取得しています。 401 Unauthorized を取得する必要がある場合。

Authorize 属性は基本認証について何も知りません。気にするのは、身元が認証されているかどうかだけです。匿名認証が有効になっているため (その場合だと思います)、Authorize 属性は適切であり、Web API が Basic スキームで資格情報を期待していることを示す WWW-Authenticate 応答ヘッダーを追加するメッセージ ハンドラー応答処理部分の 401 はありません。

于 2013-04-12T07:43:12.853 に答える