【问题标题】:SwashBuckle/Swagger - OAuth Resource Owner Password FlowSwashBuckle/Swagger - OAuth 资源所有者密码流程
【发布时间】:2016-04-28 00:35:36
【问题描述】:

我正在尝试在我的 Asp.Net Web API 中实现 swagger,但遇到了问题。

我正在使用密码资源所有者流程,我必须添加一个解决方法才能做到这一点,这在以下堆栈溢出问题中有所介绍:-

Swagger/Swashbuckle: OAuth2 with Resource Owner Password Credentials Grant

一切正常,Bearer 令牌通过 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 "接受:应用程序/json" --header “授权:承载 NqlSG-WyTx2zkYE8xFklGyZWlQDZdsCKZBHruEXvX47N7PAzw4-jZ4eH5D0yFzQTXj13RwKFFt1rUZt2fzWj1vR5UR87wdlKC3YvsTojYV4-3DsWwY7qYRfiKPuM0j09c3X5lnrtlBVJ1rBRUH0TLjfw_yGxgoLBwOJl9xyC1YWNoPOe2nzL4lMOHodAnMem0IBMJmUo3Rt575tnWAbBsQXWhlImDIxCZXvkZdJtlXfIfBSUdY9gfRWL0ZjKbf7m2-yLzH0gpMAMuKaADmJlIudJc0d4SP1Nn2Kh2HuVH8CX4QgZuu4egl9N6rY2smorP2vBSC4_dC4CpmYYzOTu2wUnUhHDY2Q6NWl377ijDKwZLcW9jtD-2tBiEGmFuRV0mVGnh0zc4w9Ao9jPCdtrbSyGitgloBW-UG2bfyao3eE” "http://localhost:42291/api/v1/claims"

我看不出这有什么问题。

然后我使用 Postman 调用完全相同的 URL 调用,使用在 javascript 调用中生成的相同访问令牌...

猜猜看……它工作正常。

编辑

我已经尝试从控制器中删除授​​权属性,以便在请求到达控制器方法时检查它。

查看请求标头,Authorization 属性为空。

不知道为什么会这样。 CURL 建议将其放入请求中。

编辑 2

我已经包含了我的安全定义:-

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

编辑 3 在此 API 调用的 Swagger UI 中显示的 cURL,当直接在命令行通过 cURL 公开时可以正常工作。

现在我完全糊涂了。

【问题讨论】:

  • 请使用 Fiddler (telerik.com/fiddler) 检查两个调用(swagger 和 postman)之间的区别。另外对于测试,我会将 add('Authorization'... 更改为 add('someUniqueKey'...
  • 你真的需要securityDefinitions吗?我没有……虽然我需要一个旧版本。
  • 我认为这个授权拒绝在管道的早期失败了,似乎我不是唯一遇到这个问题的人。我认为这可能与被 IIS 劫持的飞行前 OPTIONS 请求有关。这太糟糕了!
  • 使用 Chrome 开发人员工具 (Ctrl-Shift-I),您可以在客户端中调试 swagger... 然后您可以检查您是否 1. 获得令牌,以及 2. 令牌是否应用于您的请求...
  • 可能是 CORS 问题。确保您的 API 支持 CORS。

标签: asp.net-web-api2 swagger-ui swagger-2.0 swashbuckle


【解决方案1】:

我已经设法纠正了这个问题。这是一个简单的类型不匹配,让我伤心了好几天。

在 onComplete.JS 中,我需要创建一个与 swagger 规范中提供的键匹配的键。

如果您检查我上面的代码 sn-ps,您会看到我创建了一个密钥并将其称为“授权”。但这与命名的安全定义“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!");
        }
    });
});

为了进一步解释这一点,您需要创建 IOperationFilter 的实现,以便 swagger 可以确定 api 的哪些方法需要 Authorizaion。正确配置后,您应该会在 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);
        }
    }

【讨论】:

  • 我遇到了一个不同的问题,这为我指明了正确的方向:"oauth2", Enumerable.Empty();您需要为每种授权类型使用不同的名称,并且它们必须在 IOperationFilter 的实现中有一个条目
  • @Derek - 我尝试按照您的说明进行操作,但无法解决我的问题,请您查看我的问题stackoverflow.com/questions/47976035/…
【解决方案2】:

授权机制期望每个操作都有一个分配给它的security。如果不存在,则不会发送标头。如果您认为分配正确,请分享您的规范文件

【讨论】:

  • 嘿,我已将我的安全定义添加到问题中,您能看出它有什么问题吗?费盖
  • 我检查了我的 swagger json,auth2 标签附加到那些需要授权的方法上,所以一切看起来都是正确的。当我在 Fiddler 中查看请求时,没有 auth 标头。
猜你喜欢
  • 2023-03-19
  • 2016-02-22
  • 2015-05-30
  • 2013-10-17
  • 2018-01-29
  • 2015-05-20
  • 2019-04-08
  • 2013-11-23
  • 2017-11-14
相关资源
最近更新 更多