如何为 Kestrel 主机添加 NTLM 支持?
How do I add NTLM support for a Kestrel host?
我们想使用 Kestrel 来托管我们的网络 api。我们必须同时支持 NTLM 和协商身份验证。
Core 3.0 应该可以做到
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.0&tabs=visual-studio
然而,当 Kestrel 响应挑战时,仅返回协商方案。有没有人设法用 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();
}
}
问题是challange响应只有Negotiate
WWW-Authenticate Negotiate
我本以为 NTLM 和 Negotiate
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] 注释添加到您的控制器 类。
,而不是要求对所有控制器进行身份验证
根据 Michael 的回复,对于那些感兴趣的人,我们现在已经开始工作了
但是有一个问题。 Kestrel 不会自行发起挑战响应。我们使用类似于此的代码构建自己的
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"];
}
}
}
我们想使用 Kestrel 来托管我们的网络 api。我们必须同时支持 NTLM 和协商身份验证。
Core 3.0 应该可以做到 https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.0&tabs=visual-studio
然而,当 Kestrel 响应挑战时,仅返回协商方案。有没有人设法用 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();
}
}
问题是challange响应只有Negotiate
WWW-Authenticate Negotiate
我本以为 NTLM 和 Negotiate
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] 注释添加到您的控制器 类。
,而不是要求对所有控制器进行身份验证根据 Michael 的回复,对于那些感兴趣的人,我们现在已经开始工作了
但是有一个问题。 Kestrel 不会自行发起挑战响应。我们使用类似于此的代码构建自己的
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"];
}
}
}