Web API 与 OAUTH 使用 Swagger / Swashbuckle

Web API with OAUTH using Swagger / Swashbuckle

我正在尝试让我的 Web API 项目使用 Swagger 'pretty' 文档等。(http://swagger.io/)

我正在使用 Swashbuckle for .NET,它是从 NuGet 安装的,我使用的版本是 4.0.1

我已经能够安装和使用 Swagger。此时一切似乎都很正常。我唯一的障碍是禁用 API 密钥并能够使用 OAuth,就像在 PetStore 示例中一样 (http://petstore.swagger.wordnik.com/#!/pet/addPet)

我已经尝试了所有可以在网上找到的方法。让我在下面列出它们:

首先,这是我的 Startup.cs

public void Configuration(IAppBuilder app)
{
    var config = new HttpConfiguration();

    WebApiConfig.Register(config);

    Swashbuckle.Bootstrapper.Init(config);
}

现在,我的 SwaggerConfig.cs:

public static void Register()
{
    Swashbuckle.Bootstrapper.Init(GlobalConfiguration.Configuration);

    SwaggerSpecConfig.Customize(c =>
    {
        c.IgnoreObsoleteActions();

        c.IncludeXmlComments(GetXmlCommentsPath());

        c.ApiInfo(new Info
        {
            Title = "Work you",
            Description = "testing some stuffs",
            Contact = "Email@email.com"
        });

        c.Authorization("oauth2", new Authorization
        {
            Type = "oauth2",
            Scopes = new List<Scope>
                {
                    new Scope { ScopeId = "products.read", Description = "View products" },
                    new Scope { ScopeId = "products.manage", Description = "Manage products" }
                },
            GrantTypes = new GrantTypes
            {
                ImplicitGrant = new ImplicitGrant
                {
                    LoginEndpoint = new LoginEndpoint
                    {
                        Url = "https://www.mysecure.website.com"
                    },
                    TokenName = "access_token"
                }
            }
        });
    });


    SwaggerUiConfig.Customize(c =>
    {
        c.EnableOAuth2Support("client_id", "test-realm", "app Name");

        var thisAssembly = typeof(SwaggerConfig).Assembly;

        c.SupportHeaderParams = true;
        c.DocExpansion = DocExpansion.List;
        c.SupportedSubmitMethods = new[] { HttpMethod.Get, HttpMethod.Post, HttpMethod.Put, HttpMethod.Head };
        c.EnableDiscoveryUrlSelector();

    });

}

我有一个 SwaggerExtensions 文件夹,里面有我需要的文件。例如:

我 类 装饰有:

[ScopeAuthorize("this.scope")]

但是,OAuth 选项从未在 swagger 页面上为我显示。我也看不到应该在哪里输入自定义 headers。

我确实看到标题和文档描述、电子邮件地址等正在从 SwaggerConfig.cs 中读取,所以我知道它至少被读取了。

我想不通。 :(

有什么想法吗?

默认情况下,swagger-ui 不显示 OAuth2 集成。

要启用它,您需要按照以下步骤操作:

  1. 确保 <script src='lib/swagger-oauth.js' type='text/javascript'></script> 包含在 index.html 顶部的脚本列表中。它应该默认存在。
  2. 在 index.html 底部的 SwaggerUi 声明中,取消注释以下代码段(默认情况下已注释):

        /*
        initOAuth({
          clientId: "your-client-id",
          realm: "your-realms",
          appName: "your-app-name"
        });
        */
    

您可能希望使用自己的设置修改 clientIdrealmappName

我得到了我的解决方案。这很强大,只是不是 100% 直接配置。

以下是我采取的步骤:

安装 NuGet 包,我使用 PM> Install-Package Swashbuckle -Version 4.1.0 但 link 位于 https://www.nuget.org/packages/Swashbuckle/,我建议获取最新版本,但我知道 4.1.0 有效。 EDIT 我刚刚更新到 5.X 但它坏了。 4.1.0 有效但最新的没有。我还没有进一步研究原因。

一旦你安装了这个,你就差不多完成了。

安装将创建一个 SwaggerConfig.cs 文件。这是我使用的代码(复制自 github master)

public class SwaggerConfig
    {
        public static void Register()
        {
            Swashbuckle.Bootstrapper.Init(GlobalConfiguration.Configuration);

            SwaggerSpecConfig.Customize(c =>
            {
                c.IgnoreObsoleteActions();

                //c.SupportMultipleApiVersions(
                //    new[] { "1.0", "2.0" },
                //    ResolveVersionSupportByRouteConstraint);

                //c.PolymorphicType<Animal>(ac => ac
                //    .DiscriminateBy(a => a.Type)
                //    .SubType<Kitten>());

                c.OperationFilter<AddStandardResponseCodes>();
                c.OperationFilter<AddAuthResponseCodes>();
                c.OperationFilter<AddOAuth2Scopes>();

                //c.IncludeXmlComments(GetXmlCommentsPath());

                c.ApiInfo(new Info
                {
                    Title = "Swashbuckle Dummy",
                    Description = "For testing and experimenting with Swashbuckle features",
                    Contact = "someone@somewhere.com"
                });

                c.Authorization("oauth2", new Authorization
                {
                    Type = "oauth2",
                    Scopes = new List<Scope>
                        {
                            new Scope { ScopeId = "test1", Description = "test1" },
                            new Scope { ScopeId = "test2", Description = "test2" }
                        },
                    GrantTypes = new GrantTypes
                    {
                        ImplicitGrant = new ImplicitGrant
                        {
                            LoginEndpoint = new LoginEndpoint
                            {
                                Url = "https://your.Oauth.server/Authorize"
                            },
                            TokenName = "access_token"
                        }
                    }
                });
            });

            SwaggerUiConfig.Customize(c =>
            {
                var thisAssembly = typeof(SwaggerConfig).Assembly;

                c.SupportHeaderParams = true;
                c.DocExpansion = DocExpansion.List;
                c.SupportedSubmitMethods = new[] { HttpMethod.Get, HttpMethod.Post, HttpMethod.Put, HttpMethod.Head };
                //c.InjectJavaScript(typeof(SwaggerConfig).Assembly, "WebApplication4.SwaggerExtensions.onComplete.js");
                //c.EnableDiscoveryUrlSelector();
                //c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
                //c.InjectStylesheet(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");

                c.EnableOAuth2Support("client_id", "realm", "Swagger UI");
            });
            // NOTE: If you want to customize the generated swagger or UI, use SwaggerSpecConfig and/or SwaggerUiConfig here ...
        }
        private static string GetXmlCommentsPath()
        {
            return String.Format(@"{0}\XmlComments.xml", AppDomain.CurrentDomain.BaseDirectory);
        }

现在我们已经告诉 Swagger 我们想要使用 OAuth,这就是我们想要使用它的方式。完成了,对吧?没有。

您需要将此文件夹和文件添加到您的解决方案中:https://github.com/domaindrivendev/Swashbuckle/tree/master/Swashbuckle.Dummy.Core/SwaggerExtensions

(您只需要 .cs 文件)

确保你的命名空间是正确的...

然后,您需要在 WebAPI 中装饰您的 class,如下所示:

[ScopeAuthorize("test1")]

现在,当您 运行 它并到达 swagger 页面时,您将看到具有该声明的每个操作都将在右上角显示 OAuth 开关。单击它时,您可以使用隐式授权流程并获得将添加到您的请求中的令牌。

这仅适用于我发现的隐式授权。看起来他们确实试图让 AuthorizationCode Grant 继续运行,但他们构建的 js 文件仅支持隐式,据我所知。

希望这对某人有所帮助。这是一个强大的工具,我希望我们看到更多的网站使用这样的工具。

谢谢,祝你好运!

我觉得你原来的大部分都没问题。我正在使用 Swashbuckle 5.2.1 并且运行良好。我刚刚写了一篇博客 post (http://knowyourtoolset.com/2015/08/secure-web-apis-with-swagger-swashbuckle-and-oauth2-part-2/) 详细解释了这一点,但要点是添加 OperationFilter class(es) 来定义你的 API 方法将获得 OAuth21 切换按钮。如上所述,GitHub 的 SwaggerExtensions 文件夹中有这些定义的(示例),但实际上您至少需要一个 class 实现 IOperationFilter 及其 Apply 方法。我在下面有一个示例 class。 class 名称真的无关紧要(它在哪里也不重要),您只需要将它(以及任何其他名称,如果您有更多)包含在指定 OperationFilter(s) 的 SwaggerConfig 中。

 public class AssignOAuth2SecurityRequirements : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
        var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any();
        if (allowsAnonymous)
            return; // must be an anonymous method


        //var scopes = apiDescription.ActionDescriptor.GetFilterPipeline()
        //    .Select(filterInfo => filterInfo.Instance)
        //    .OfType<AllowAnonymousAttribute>()
        //    .SelectMany(attr => attr.Roles.Split(','))
        //    .Distinct();

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

        var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
        {
            {"oauth2", new List<string> {"sampleapi"}}
        };

        operation.security.Add(oAuthRequirements);
    }
}