我正在实施 Swagger UI 在我的Asp.net WEB Api项目中,我使用了默认的 System.Web.Http.AuthorizeAttribute
我已经把它登记在我的 WebApiConfig.cs
在 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的Git仓库 但我找不到任何解决办法。
我也曾在 在Github上开了一个问题
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);
}
}