我正在使用Asp.Net Core 2.1 Web Api和Swashbuckle.aspnetcore.swagger
在授予访问权限之前,我想用用户名和密码保护api文档页面。
样本文档页面qazxsw poi
确保公众无法访问它
在.NET Core中,您使用中间件而不是DelegatingHandler:
mguinness's answer on Github
您还需要一个扩展方法来帮助添加管道:
public class SwaggerAuthorizedMiddleware
{
private readonly RequestDelegate _next;
public SwaggerAuthorizedMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.StartsWithSegments("/swagger")
&& !context.User.Identity.IsAuthenticated)
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return;
}
await _next.Invoke(context);
}
}
然后在使用Swagger之前添加到Startup.cs中的Configure方法:
public static class SwaggerAuthorizeExtensions
{
public static IApplicationBuilder UseSwaggerAuthorized(this IApplicationBuilder builder)
{
return builder.UseMiddleware<SwaggerAuthorizedMiddleware>();
}
}
在那里还有一个变种解决方案app.UseSwaggerAuthorized();
app.UseSwagger();
app.UseSwaggerUi();
。
我在git中找到了解决方案并应用于我的项目。它按预期工作。
下面的代码从那里复制。
how to do it with basic auth
在Startup.cs中
public class SwaggerBasicAuthMiddleware
{
private readonly RequestDelegate next;
public SwaggerBasicAuthMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task InvokeAsync(HttpContext context)
{
//Make sure we are hitting the swagger path, and not doing it locally as it just gets annoying :-)
if (context.Request.Path.StartsWithSegments("/swagger") && !this.IsLocalRequest(context))
{
string authHeader = context.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic "))
{
// Get the encoded username and password
var encodedUsernamePassword = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim();
// Decode from Base64 to string
var decodedUsernamePassword = Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword));
// Split username and password
var username = decodedUsernamePassword.Split(':', 2)[0];
var password = decodedUsernamePassword.Split(':', 2)[1];
// Check if login is correct
if (IsAuthorized(username, password))
{
await next.Invoke(context);
return;
}
}
// Return authentication type (causes browser to show login dialog)
context.Response.Headers["WWW-Authenticate"] = "Basic";
// Return unauthorized
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
else
{
await next.Invoke(context);
}
}
public bool IsAuthorized(string username, string password)
{
// Check that username and password are correct
return username.Equals("SpecialUser", StringComparison.InvariantCultureIgnoreCase)
&& password.Equals("SpecialPassword1");
}
public bool IsLocalRequest(HttpContext context)
{
//Handle running using the Microsoft.AspNetCore.TestHost and the site being run entirely locally in memory without an actual TCP/IP connection
if (context.Connection.RemoteIpAddress == null && context.Connection.LocalIpAddress == null)
{
return true;
}
if (context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress))
{
return true;
}
if (IPAddress.IsLoopback(context.Connection.RemoteIpAddress))
{
return true;
}
return false;
}
}
public static class SwaggerAuthorizeExtensions
{
public static IApplicationBuilder UseSwaggerAuthorized(this IApplicationBuilder builder)
{
return builder.UseMiddleware<SwaggerBasicAuthMiddleware>();
}
}