全局授权过滤器不适用于Swagger UI Asp.net Web Api [英] Global Authorize filter not working with Swagger UI Asp.net Web Api

查看:171
本文介绍了全局授权过滤器不适用于Swagger UI Asp.net Web Api的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用我的Asp.net WEB Api项目实现 Swagger UI 使用默认的 System.Web.Http.AuthorizeAttribute ,我已经将它注册在 WebApiConfig.cs 中的 Register 方法中,作为

I am implementing Swagger UI with my Asp.net WEB Api project, I am using the default System.Web.Http.AuthorizeAttribute, I have registered it in my WebApiConfig.cs in Register method as

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

我已将Swagger UI实现为

I have implemented Swagger UI as

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中心存储库中搜索解决方案,但我找不到任何解决方案.

I have also tried to search the solution on Swashbuckle's Git hub repository but I couldn't find any solution.

我也遇到过在Github上对此问题已打开的问题

推荐答案

Swashbuckle中的Swagger API和UI是

Swagger API and UI in Swashbuckle are implemented as HttpMessageHandler for route. So filters doesn't work there (because they work only for ASP.NET WebAPI's controllers and actions).

但是,您可以防止未经授权地使用不同的招摇方式.如果您将ASP.NET Web API用作Owin中间件(通过使用 Microsoft.AspNet.WebApi.Owin nuget包),则可以编写简单的中间件,并将其放在swagger中间件之前,以拒绝对"swagger/docs/"和"swagger/ui/"的请求(Swagger API的默认路由)和用户界面).

However, you can protect from unathorized access to swagger differently. If you use ASP.NET Web API as Owin middleware (by use of Microsoft.AspNet.WebApi.Owin nuget package) then you can write simple middleware and put it before swagger middleware to reject requests to "swagger/docs/" and "swagger/ui/" (default routes for Swagger API and 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中间件之前(还增加了麻烦),您可以使用自定义身份验证逻辑放置自己的中间件.

ConfigureAuth(app) is a middleware responsible for authentication (here generated by Visual Studio template which uses ASP.NET Identity for it). After auth middleware and before WebApi middleware (which adds also swagger) you can put you own middleware with custom authentication logic.

如果您不将Owin用于ASP.NET API,则可以尝试实现 HttpMessageHandler ,并在其中添加类似上一个OWIN中间件示例的逻辑.您应该能够使用

If you don't use Owin for ASP.NET API then you can try to implement HttpMessageHandler and add there similar logic like in previous OWIN middleware example. You should be able to use Thread.CurrentPrincipal to get authorization data (or HttpContext.Current.User when hosting in IIS? I'm not sure about that):

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

这篇关于全局授权过滤器不适用于Swagger UI Asp.net Web Api的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆