6

Asp.Net Web API に Swagger を実装しようとしていますが、問題が発生しています。

私はパスワード リソース オーナー フローを使用しています。これを行うには回避策を追加する必要があります。これについては、次のスタック オーバーフローの質問で説明します。

Swagger/Swashbuckle: OAuth2 とリソース所有者のパスワード認証情報付与

すべてが機能しています。ベアラー トークンは JavaScript を介して現在のブラウザー ウィンドウのリクエスト ヘッダーに追加されますが、承認を必要とするコントローラー メソッドへの API 呼び出しは「401 - 承認に失敗しました」を返します。

ベアラー トークンを取得してヘッダーを追加する JavaScript は次のとおりです。

 $('#input_apiKey').change(function () {
    var key = $('#input_apiKey')[0].value;
    var credentials = key.split(':'); //username:password expected
    $.ajax({
        url: "http://localhost:42291/token",
        type: "post",
        contenttype: 'x-www-form-urlencoded',
        data: "grant_type=password&username=" + credentials[0] + "&password=" + credentials[1],
        success: function (response) {
            var bearerToken = 'Bearer ' + response.access_token;

            window.swaggerUi.api.clientAuthorizations.add('Authorization', new window.SwaggerClient.ApiKeyAuthorization('Authorization', bearerToken, 'header'));
            window.swaggerUi.api.clientAuthorizations.remove('api_key');

            alert("Login Succesfull!");
        },
        error: function (xhr, ajaxoptions, thrownerror) {
            alert("Login failed!");
        }
    });
}); 

Swagger の応答の Curl は次のとおりです。

curl -X GET --header "Accept: application/json" --header "Authorization: Bearer NqlSG-WyTx2zkYE8xFklGyZWlQDZdsCKZBHruEXvX47N7PAzw4-jZ4eH5D0yFzQTXj13RwKFFt1rUZt2fzWj1vR5UR87wdlKC3YvsTojYV4-3DsWwY7qYRfiKPuM0j09c3X5lnrtlBVJ1rBRUH0TLjfw_yGxgoLBwOJl9xyC1YWNoPOe2nzL4lMOHodAnMem0IBMJmUo3Rt575tnWAbBsQXWhlImDIxCZXvkZdJtlXfIfBSUdY9gfRWL0ZjKbf7m2-yLzH0gpMAMuKaADmJlIudJc0d4SP1Nn2Kh2HuVH8CX4QgZuu4egl9N6rY2smorP2vBSC4_dC4CpmYYzOTu2wUnUhHDY2Q6NWl377ijDKwZLcW9jtD-2tBiEGmFuRV0mVGnh0zc4w9Ao9jPCdtrbSyGitgloBW-UG2bfyao3eE" " http://localhost:42291/api/v1/claims "

これにはまったく問題がありません。

次に、Postman を使用して、javascript 呼び出しで生成されたのと同じアクセス トークンを使用して、まったく同じ URL 呼び出しを呼び出しました...

何を推測します...それはうまくいきます。

編集

コントローラーから認証属性を削除しようとしたので、コントローラーメソッドにヒットしたときにリクエストを確認できます。

要求ヘッダーを見ると、Authorization プロパティは null です。

これがなぜなのかわかりません。CURL は、リクエストに配置されたことを示しています。

編集2

私のセキュリティ定義を含めました:-

"securityDefinitions": {
        "oauth2": {
            "type": "oauth2",
            "description": "OAuth2 Password Grant",
            "flow": "password",
            "tokenUrl": "http://localhost:42291/token",
            "scopes": {}
        }
    }

編集 3 この API 呼び出しの Swagger UI に表示される cURL は、コマンド ラインで直接 cURL を介して公開すると、問題なく動作します。

今、私は完全に混乱しています。

4

2 に答える 2

8

問題を修正することができました。何日もの間私を悩ませたのは、単純な型の不一致でした。

onComplete.JS では、swagger 仕様で提示されたキーと一致するキーを作成する必要がありました。

上記のコード スニペットを調べると、キーを作成して「Authorization」と呼んでいることがわかります。しかし、それは名前付きセキュリティ定義「oauth2」と一致しません。

作業コード:-

$('#input_apiKey').change(function () {
    var key = $('#input_apiKey')[0].value;
    var credentials = key.split(':'); 
    $.ajax({
        url: "http://localhost:42291/token",
        type: "post",
        contenttype: 'x-www-form-urlencoded',
        data: "grant_type=password&username=" + credentials[0] + "&password=" + credentials[1],
        success: function (response) {

            var bearerToken = "Bearer " + response.access_token;

            window.swaggerUi.api.clientAuthorizations.remove('api_key');

            var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("Authorization", bearerToken, "header");

            window.swaggerUi.api.clientAuthorizations.add('oauth2', apiKeyAuth);

            alert("Login Succesfull!");

        },
        error: function (xhr, ajaxoptions, thrownerror) {
            alert("Login failed!");
        }
    });
});

これをもう少し詳しく説明すると、API のどのメソッドが Authorizaion を必要とするかを swagger が判断できるように、IOperationFilter の実装を作成する必要があります。これを正しく構成すると、swagger 仕様の各 API 呼び出しに対するセキュリティ定義が表示されます。

ここに画像の説明を入力

IOperationFilter の私の実装:-

public class AssignOAuth2SecurityRequirements : IOperationFilter
    {
        /// <summary>
        /// Apply Security Measures.
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="schemaRegistry"></param>
        /// <param name="apiDescription"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            // Determine if the operation has the Authorize attribute
            var authorizeAttributes = apiDescription.ActionDescriptor.GetCustomAttributes<AuthorizeAttribute>();

            if (!authorizeAttributes.Any())
                return;

            // Initialize the operation.security property
            if (operation.security == null)
                operation.security = new List<IDictionary<string, IEnumerable<string>>>();

            // Add the appropriate security definition to the operation
            var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
            {
                { "oauth2", Enumerable.Empty<string>() }
            };

            operation.security.Add(oAuthRequirements);
        }
    }
于 2016-01-29T08:31:15.763 に答える
3

security認可メカニズムは、各操作に が割り当てられていることを想定しています。存在しない場合、ヘッダーは送信されません。適切に割り当てられていると思われる場合は、仕様ファイルを共有してください

于 2016-01-26T21:50:37.637 に答える