如何为 Kestrel 主机添加 NTLM 支持?



我们想使用Kestrel来托管我们的web-api。我们必须同时支持 NTLM 和协商身份验证。

这在Core 3.0中应该是可能的。 https://learn.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.0&tabs=visual-studio

但是,当红隼响应挑战时,仅返回协商方案。有没有人设法使用 Kestrel 实现 NTLM 身份验证?

该应用程序在 Windows 10 计算机上运行

基本上,我们遵循了建议。首先向服务添加身份验证:

services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();

然后将身份验证添加到管道

app.UseAuthentication();

同样在管道中,我们有自己的中间件,以确保用户已经过验证

app.UseMiddleware<ValidateAuthentication>();

实现如下所示

internal class ValidateAuthentication : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (context.User.Identity.IsAuthenticated)
await next(context);
else
await context.ChallengeAsync();
}
}

问题是质询响应只有协商

WWW-Authenticate Negotiate

我本来期望NTLM和谈判

WWW-Authenticate NTLM, Negotiate

您可以重写 HandleChallengeAsync 方法,然后替换处理程序:

public sealed class NtlmNegotiateHandler : NegotiateHandler
{
public NtlmNegotiateHandler(
IOptionsMonitor<NegotiateOptions> options, 
ILoggerFactory logger, UrlEncoder encoder, 
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
{
await base.HandleChallengeAsync(properties);
if (Response.StatusCode ==  StatusCodes.Status401Unauthorized)
{
Response.Headers.Append(Microsoft.Net.Http.Headers.HeaderNames.WWWAuthenticate, "NTLM");
}
}
}
public sealed class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
// replace the handler
var serviceDescriptor = new ServiceDescriptor(typeof(NegotiateHandler), 
typeof(NtlmNegotiateHandler), 
ServiceLifetime.Transient);
services.Replace(serviceDescriptor);
}
}

对于 .NET 6

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
app.UseAuthorization();
app.MapControllers().RequireAuthorization();

或者,您可以向控制器类添加 [Authorize] 注释,而不是要求对所有控制器进行身份验证。

对于那些感兴趣的人,我们现在根据迈克尔的回应进行了这项工作

然而,有一个问题。红隼不会自行发起质询响应。我们用类似于下面的代码构建自己的代码

public class ValidateAuthentication : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (context.Request.Method == "OPTIONS")
{
await next(context);
return;
}
if (context.User.Identity != null && context.User.Identity.IsAuthenticated)
{
await next(context);
}
else
{
context.Response.StatusCode = 401;
context.Response.Headers["Proxy-Authenticate"] = "Negotiate";
context.Response.Headers["WWW-Authenticate"] = "Negotiate";
context.Response.Headers["Access-Control-Allow-Origin"] = context.Request.Headers["Origin"];
}
}
}

最新更新