全局授权过滤器不能与Swagger UI Asp.net Web Api一起使用。

问题描述 投票:1回答:1

我正在实施 Swagger UI 在我的Asp.net WEB Api项目中,我使用了默认的 System.Web.Http.AuthorizeAttribute我已经把它登记在我的 WebApiConfig.csRegister 方法为

 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的Git仓库 但我找不到任何解决办法。

我也曾在 在Github上开了一个问题

asp.net-web-api authorization swagger-ui swashbuckle
1个回答
0
投票

Swashbuckle中的Swagger API和UI是什么?实施 作为 HttpMessageHandler 的路由。所以过滤器在那里不起作用(因为它们只对 ASP.NET WebAPI 的控制器和动作起作用)。

然而,你可以用不同的方法来防止未经授权的访问swagger。如果你使用ASP.NET Web API作为Owin的中间件(通过使用 Microsoft.AspNet.WebApi.Owin nuget包),那么你可以写一些简单的中间件,并把它放在swagger中间件之前,以拒绝对 "swaggerdocs "和 "swaggerui"(swagger API和UI的默认路由)的请求。

例如,"swaggerdocs "和 "swaggerui"(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) 是一个负责身份验证的中间件(这里由Visual Studio模板生成,它使用ASP.NET Identity作为模板)。在auth中间件之后,在WebApi中间件之前(它也添加了swagger),你可以把你自己的中间件和自定义的认证逻辑放在一起。

如果你没有使用Owin for ASP.NET API,那么你可以尝试实现以下功能 HttpMessageHandler 并在其中添加类似于之前的OWIN中间件示例的逻辑。您应该能够使用 Thread.CurrentPrincipal 以获取授权数据(或 HttpContext.Current.User 在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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.