使用Swagger / Swashbuckle实现带有OAUTH的Web API

17

我试图让我的Web API项目使用Swagger“漂亮”的文档等(http://swagger.io/)。

我正在使用从NuGet安装的.NET的Swashbuckle,我使用的版本是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文件夹,在其中我有应该所需的文件。例如:

SwaggerExt所需文件

我有用装饰符(decorator)修饰的类:

[ScopeAuthorize("this.scope")]

然而,在我的Swagger页面上,OAuth选项从未显示。我也看不到我应该输入自定义标头的位置。

我可以看到标题和文档描述、电子邮件地址等是从SwaggerConfig.cs中读取的,所以我知道它至少已经被读取。

我无法弄清楚问题所在。 :(

有什么想法吗?

3个回答

9
我已经找到了解决方案。这个工具很强大,但配置并不是100%的直截了当。
以下是我的步骤:
1. 安装 NuGet 包,我使用了 PM> Install-Package Swashbuckle -Version 4.1.0,但链接在 https://www.nuget.org/packages/Swashbuckle/,建议获取最新版本,但我知道 4.1.0 可以工作。 编辑 我刚刚更新到了 5.X,但它破坏了它。4.1.0 可以工作,但最新版不行。我还没有深入研究为什么。
2. 安装完成后,你就快可以完成整个操作了。
3. 安装将会创建一个 SwaggerConfig.cs 文件。这是我使用的代码(从 github 主分支复制)
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中的类:
[ScopeAuthorize("test1")]

现在,当您运行它并打开swagger页面时,您将看到具有该声明的每个操作都在右上角具有OAuth开关。单击它后,您可以使用隐式授权流程获取令牌,并将其添加到您的请求中。
据我所知,这只适用于隐式授权。看起来他们已经尝试过使用AuthorizationCode授权,但是从我所看到的js文件来看,他们只支持隐式授权。
希望这能帮助某些人。这是一个强大的工具,我希望我们能看到更多的网站使用类似的东西。
谢谢,祝好运!

8

我认为你最初的大部分内容都可以。我正在使用Swashbuckle 5.2.1,并且已经将它们很好地工作了起来。我刚刚写了一篇博客文章 (http://knowyourtoolset.com/2015/08/secure-web-apis-with-swagger-swashbuckle-and-oauth2-part-2/),其中详细解释了这一点,但本质上是添加OperationFilter类,以定义您的API方法中哪些会获得OAuth21切换按钮。在GitHub的SwaggerExtensions文件夹中有(样本)定义,但实际上,您只需要至少一个实现IOperationFilter及其Apply方法的类。下面是一个示例类。类名并不重要(也不关心位置),您只需要在SwaggerConfig中包含它(如果有更多,则还需要包括其他操作过滤器(OperationFilter))。

 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);
    }
}

我该如何告诉Swagger在获取令牌时需要请求哪些范围? - Giorgi
在SwaggerConfig.cs文件中,有一个OAuth2部分,应该最终看起来像这样(最初被注释掉): c.OAuth2("oauth2") ..... .Scopes(scopes => { scopes.Add("managerapi", "DESCRIPTION"); });“oauth2”字符串必须与我的原始响应中显示的字符串匹配。 - Erik Dahl

-1

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

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

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

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

您可能需要根据自己的设置修改clientIdrealmappName


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接