【发布时间】:2016-03-08 20:05:32
【问题描述】:
在我的 Azure Mobile .NET 后端中,我想使用 Azure Mobile .NET Server Swagger 。我正在寻找从公共访问中隐藏招摇 UI 的快速方法?有没有办法只为选定的用户提供访问权限?
【问题讨论】:
标签: azure azure-mobile-services swagger swagger-ui
在我的 Azure Mobile .NET 后端中,我想使用 Azure Mobile .NET Server Swagger 。我正在寻找从公共访问中隐藏招摇 UI 的快速方法?有没有办法只为选定的用户提供访问权限?
【问题讨论】:
标签: azure azure-mobile-services swagger swagger-ui
首先声明:即使您保护 Swagger UI 不被公开使用,也不能保护您的 API 不被公开使用。您必须假设每个人都知道您的所有路线,并且有适当的安全措施来保护可能进来的任何请求。
话虽如此,但仍然没有一种简单的方法可以做到这一点。 Swashbuckle(将 Swagger 添加到 Web API 的部分)将自定义 HttpMessageHandler 添加到 /swagger/ui 路由(如 here 所示)。如果你查看Web API pipeline,你可以看到如果你指定一个自定义处理程序,你可以绕过所有的Controller选择、Auth过滤器等。这就是这里发生的事情。
一些解决方案:
ConfigureSwagger(config)。这将阻止所有/swagger 路由将其投入生产。或者您可以使用暂存槽并仅将其添加到那里。SwaggerUiHandler。如果他们去/swagger/ui 路线,这将提示用户提供基本信用。请参阅下面的代码修改版本。也许我们可以想出一个更好的解决方案——我在 Swashbuckle 存储库中看到几个问题(here 和 here)表明你不是第一个遇到这个问题的人.
修改后的 BasicAuthHandler(来自here):
警告:最低限度的测试(并确保更改验证用户/通过的方式)
public class BasicAuthMessageHandler : DelegatingHandler
{
private const string BasicAuthResponseHeader = "WWW-Authenticate";
private const string BasicAuthResponseHeaderValue = "Basic";
public BasicAuthMessageHandler(HttpMessageHandler innerHandler)
{
this.InnerHandler = innerHandler;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
AuthenticationHeaderValue authValue = request.Headers.Authorization;
HttpResponseMessage unauthorizedResponse = request.CreateUnauthorizedResponse();
if (authValue != null && !string.IsNullOrWhiteSpace(authValue.Parameter))
{
Credentials parsedCredentials = ParseAuthorizationHeader(authValue.Parameter);
if (parsedCredentials != null)
{
// TODO: Check that the user/pass are valid
if (parsedCredentials.Username == "user" &&
parsedCredentials.Password == "pass")
{
// If match, pass along to the inner handler
return base.SendAsync(request, cancellationToken);
}
}
}
else
{
// Prompt for creds
unauthorizedResponse.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue);
}
return Task.FromResult(unauthorizedResponse);
}
private Credentials ParseAuthorizationHeader(string authHeader)
{
string[] credentials = Encoding.ASCII.GetString(Convert
.FromBase64String(authHeader))
.Split(
new[] { ':' });
if (credentials.Length != 2 || string.IsNullOrEmpty(credentials[0])
|| string.IsNullOrEmpty(credentials[1])) return null;
return new Credentials()
{
Username = credentials[0],
Password = credentials[1],
};
}
}
注册 Swagger 路线
// Do this after calling ConfigureSwagger
ConfigureSwagger(config);
// Remove the swagger_ui route and re-add it with the wrapped handler.
var route = config.Routes["swagger_ui"];
config.Routes.Remove("swagger_ui");
config.Routes.MapHttpRoute("swagger_ui", route.RouteTemplate, route.Defaults, route.Constraints, new BasicAuthMessageHandler(route.Handler));
【讨论】: