全局授权过滤器不适用于 Swagger UI Asp.net Web Api

2024-02-04

我正在实施招摇的用户界面 https://swagger.io/tools/swagger-ui/对于我的 Asp.net WEB Api 项目,我使用默认值System.Web.Http.AuthorizeAttribute,我已将其注册到我的WebApiConfig.cs in Register方法如

 config.Filters.Add(new AuthorizeAttribute());

我已将 Swagger UI 实现为

public static void Register()
{
 var thisAssembly = typeof(SwaggerConfig).Assembly;

 GlobalConfiguration.Configuration
 .EnableSwagger(c =>
 {
    c.SingleApiVersion("v1", "COE.Services.WebAPI");

    c.OAuth2("oauth2")
    .Description("OAuth2 Implicit Grant")
    .Flow("implicit")
    .AuthorizationUrl(configurationService.BaseWithTokenUrl)
    .Scopes(scopes =>
    {
        scopes.Add("user_scope", "Access REST API");
    });

    c.OperationFilter<AssignOAuth2SecurityRequirements>();
})
.EnableSwaggerUi(c =>
{
    c.EnableOAuth2Support("COEApi", configurationService.BaseUrl + "swagger/ui/o2c-html", "Swagger");
});
}     

 public class AssignOAuth2SecurityRequirements : IOperationFilter
 {
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        var toBeAuthorize = apiDescription.GetControllerAndActionAttributes<AuthorizeAttribute>().Any();
        var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();

        if (toBeAuthorize && !allowAnonymous)
        {
            if (operation.parameters == null)
                operation.parameters = new List<Parameter>();

            operation.parameters.Add(new Parameter()
            {
                name = "Authorization",
                @in = "header",
                description = "Bearer <token>",
                required = true,
                type = "string"
            });
        }
    }
}

我也尝试过搜索解决方案Swashbuckle Github 存储库 https://github.com/mattfrear/Swashbuckle.AspNetCore.Filters但我找不到任何解决方案。

我也遇到过在 Github 上打开了有关此问题的问题 https://github.com/mattfrear/Swashbuckle.AspNetCore.Filters/issues/93


Swashbuckle 中的 Swagger API 和 UI 是实施的 https://github.com/domaindrivendev/Swashbuckle/blob/master/Swashbuckle.Core/Application/HttpConfigurationExtensions.cs#L91 as HttpMessageHandler为路线。因此过滤器在那里不起作用(因为它们仅适用于 ASP.NET WebAPI 的控制器和操作)。

但是,您可以以不同的方式防止未经授权的访问 swagger。如果您使用 ASP.NET Web API 作为 Owin 中间件(通过使用微软.AspNet.WebApi.Owin https://www.nuget.org/packages/Microsoft.AspNet.WebApi.Owin/5.2.7nuget 包),那么你可以编写简单的中间件并将其放在 swagger 中间件之前,以拒绝对“swagger/docs/”和“swagger/ui/”(Swagger API 和 UI 的默认路由)的请求。

例如:

[assembly: OwinStartupAttribute(typeof(WebApplicationMvcWebApiSwagger.Startup))]
namespace WebApplicationMvcWebApiSwagger
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);

            app.UseRejectUnathorizedUsersForSwagger();

            var config = new HttpConfiguration();

            config
                .EnableSwagger(c =>
                {
                    c.SingleApiVersion("v1", "A title for your API");
                })
                .EnableSwaggerUi();

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            app.UseWebApi(config);
        }
    }

    public static class SwaggerAuthorizationMiddleware
    {
        public static void UseRejectUnathorizedUsersForSwagger(this IAppBuilder appBuilder)
        {
            appBuilder.Use((context, next) =>
            {
                if (context.Request.Path.Value.StartsWith("/swagger/docs/")
                    || context.Request.Path.Value.StartsWith("/swagger/ui/"))
                {
                    var user = (context.Request.User as ClaimsPrincipal);
                    if (user == null || !user.Identity.IsAuthenticated)
                    {
                        context.Response.StatusCode = 401;
                        context.Response.ContentType = "text/plain";
                        return context.Response.WriteAsync("Unauthorized. Log in to use swagger.");
                    }
                }

                return next.Invoke();
            });
        }
    }
}

ConfigureAuth(app)是一个负责身份验证的中间件(此处由使用 ASP.NET Identity 的 Visual Studio 模板生成)。在 auth 中间件之后和 WebApi 中间件之前(这也增加了 swagger),您可以将自己的中间件与自定义身份验证逻辑一起放置。

如果您不使用 Owin for ASP.NET API 那么您可以尝试实现HttpMessageHandler并添加与之前的 OWIN 中间件示例类似的逻辑。你应该能够使用Thread.CurrentPrincipal https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api#authentication获取授权数据(或HttpContext.Current.User https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api#setting-the-principal在 IIS 中托管时?对此我不确定):

protected void Application_Start()
{
    //...
    GlobalConfiguration.Configure(WebApiConfig.Register);
    //...
}
config.MessageHandlers.Add(new RequireAdminUserForSwaggerDocAndUiHandler());

config
    .EnableSwagger(c =>
    {
        c.SingleApiVersion("v1", "A title for your API");
    })
    .EnableSwaggerUi();

config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);
public class RequireAdminUserForSwaggerDocAndUiHandler : DelegatingHandler
{
    async protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.RequestUri.PathAndQuery.StartsWith("/swagger/docs/")
            || request.RequestUri.PathAndQuery.StartsWith("/swagger/ui/"))
        {
            if (Thread.CurrentPrincipal == null || !Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                var response = new HttpResponseMessage();
                response.StatusCode = System.Net.HttpStatusCode.Unauthorized;
                response.Content = new StringContent("Unauthorized. Log in to use swagger.");
                return response;
            }
        }

        return await base.SendAsync(request, cancellationToken);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

全局授权过滤器不适用于 Swagger UI Asp.net Web Api 的相关文章

随机推荐

  • 如何在 Struts 2 的 OGNL 表达式语言中包含 HTML

    我正在研究 struts 2 我正在做一个projection我的 JSP 页面中使用 OGNL 表达式语言的集合 我有 1 个基于列表的集合action类 我在 JSP 页面上访问该类 如下所示
  • 如何使用凭证配置文件通过 AWS CLI 登录

    我想设置多个 AWS 配置文件 以便在项目之间跳转时可以轻松更改设置和凭证 我已阅读 AWS 文档 但关于如何选择登录时要使用的配置文件非常模糊 当我尝试登录时 它只是给我这个错误 这似乎表明它没有获取任何凭据 An error occur
  • 模块联合无法在 webpack.config.js 中动态挂接远程

    当我在 index html 中预先加载遥控器时 我已经进行了模块联合设置并且工作正常 下面的作品 index html div div host webpack name home library type var name home f
  • pybind11、cmake:如何安装文件?

    我正在将 C 库与越来越流行的接口连接起来pybind11 https github com pybind pybind11获取本机 Python 绑定 配置是通过CMake My CMakeLists txt好像 cmake minimu
  • Docker 构建时出现“组织已启用或强制执行 SAML SSO。要访问远程:此存储库”错误

    FROM golang 1 17 alpine as builder ENV GOPRIVATE github com XXXXX ARG GITHUB TOKEN GITHUB TOKEN RUN apk update apk add g
  • HTML/CSS 显示/隐藏多个元素?

    我正在寻找一个 HTML CSS 解决方案来应对这一挑战 我有多个具有相同类或相同 id 的元素 并且我想使用按钮或切换开关同时显示 隐藏它们 然后我有一个单击事件 当我单击代表所有这些元素的类或 ID 时 它们都会隐藏 当我再次单击时 它
  • Laravel 存储文件的公共 url

    我想检索使用存储的所有文件的公共网址 存储 putFile 公共 备件 所以 这是我正在使用的问题 存储 文件 公共 备件 但它提供了 laravel 存储目录的输出 public spares image1 jpg public spar
  • 应用程序退出后未设置剪贴板?

    以这个例子为例如何使用 Python 将字符串复制到 Windows 上的剪贴板 https stackoverflow com questions 579687 how do i copy a string to the clipboar
  • 我可以使用 Linux/Mono 部署 aspnet web 应用程序吗?

    我有一个 C ASP NET 应用程序 可以在带有 IIS 的 Windows 上运行 但最近我很想切换到 Linux Mono 它提出了一些问题 我可以在 Mono 中正确运行我的 Visual Studio 项目和源代码吗 我的客户使用
  • 无法运行growl通知并且gemgrowl_notify抛出错误

    当我运行 guard 时 我无法收到咆哮通知 我需要growl notify 的任何特定版本吗 咆哮版本 1 2 这是我的宝石文件 gem rails 3 1 3 gem sqlite3 group development test do
  • 如何按值对计数器进行排序? - Python

    除了进行反向列表理解的列表理解之外 是否有一种Pythonic方法可以按值对Counter进行排序 如果是这样 它比这个更快 gt gt gt from collections import Counter gt gt gt x Count
  • 如何加载和解析 SVG 文档

    背景 有许多与读取和解析 SVG 路径相关的未解答问题 用Java读取svg路径数据的最简单方法 https stackoverflow com questions 21973777 回复 使用 batik svg 解析器解析 svg 文件
  • 如何获取 Invoke-AzureRmVMRunCommand 命令的输出流?

    我正在尝试运行以下命令 Invoke AzVMRunCommand ResourceGroupName instance ResourceGroupName Name instance Name CommandId RunPowerShel
  • Sequelize 设置时区进行查询

    我目前正在使用续集 with postgres在我的项目中 我需要更改查询 因此它返回带有时区偏移量的created at列 var sequelize new Sequelize connStr dialectOptions useUTC
  • DynamoDB query() 与 getItem() 基于索引进行单项检索

    如果我根据索引哈希键从表中检索单个项目 两者之间是否存在性能差异query or getItem getItem会更快 getItem通过哈希和范围键检索是 1 1 匹配 检索它所需的时间 因此性能 受到内部哈希和分片的限制 查询结果是对
  • 如何将 AJAX 成功变量存储为 AJAX 之外的变量?

    我使用 AJAX 来获取我命名为变量 myPubscore 的数据 现在我尝试将 myPubscore 发送到另一个 js 文件 myPubscore 在 Ajax 中打印得很好 但是当我在 sendResponse 之前打印时 我收到 事
  • 如何从数组中获取最多代表的对象

    我有一个包含一些对象的数组 并且有几个相似的对象 例如 水果 苹果 橙子 苹果 香蕉 香蕉 橙子 苹果 苹果 从该数组中获取最多代表的对象的最有效方法是什么 在这种情况下 它将是 apple 但是您将如何有效地计算它呢 不要重新发明轮子 在
  • google.load 导致 dom/screen 为空

    我正在尝试异步添加谷歌可视化 但遇到了问题 我已将范围缩小到导致问题的 google load 当 google load 部分 js 运行时 我得到一个空的屏幕 dom 任何人都知道我做错了什么 我也尝试过使用 google setOnL
  • 推送秘密变更集

    这可能看起来很矛盾 我知道秘密变更集应该是私有的 但是如果我想备份这些秘密变更集怎么办 我并行处理一些分支 有时我想推送一个分支 但不想推送其他分支 为了实现这一目标 我在不同的克隆中工作 但我讨厌那样 所以现在 Mercurial 有阶段
  • 全局授权过滤器不适用于 Swagger UI Asp.net Web Api

    我正在实施招摇的用户界面 https swagger io tools swagger ui 对于我的 Asp net WEB Api 项目 我使用默认值System Web Http AuthorizeAttribute 我已将其注册到我