全局授权过滤器不适用于Swagger UI Asp.net Web Api [英] Global Authorize filter not working with 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上对此问题已打开的问题
推荐答案
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中间件示例的逻辑.您应该能够使用 HttpContext.Current.User ?我不确定):
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屋!