如何为 Kestrel 主机添加 NTLM 支持?
Posted
技术标签:
【中文标题】如何为 Kestrel 主机添加 NTLM 支持?【英文标题】:How do I add NTLM support for a Kestrel host? 【发布时间】:2020-02-07 15:43:21 【问题描述】:我们想使用 Kestrel 来托管我们的 web-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();
问题是挑战响应只有协商
WWW-Authenticate Negotiate
我本来期望 NTLM 和协商
WWW-Authenticate NTLM, Negotiate
【问题讨论】:
【参考方案1】:您可以覆盖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);
【讨论】:
谢谢 Andriy 现在看来挑战是正确的。并且通过正确的挑战,我的客户将响应一个包括 NTLM 令牌的新请求。只有服务仍然无法进行身份验证。我想我也必须重写 HandleAuthenticateAsync 。只有我不知道如何验证 NTLM 令牌?【参考方案2】:对于 .NET 6
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
app.UseAuthorization();
app.MapControllers().RequireAuthorization();
或者您可以将 [Authorize] 注释添加到您的控制器类中,而不是要求所有控制器进行身份验证。
【讨论】:
谢谢@Michal 这真的很有帮助。我们的团队肯定会使用它【参考方案3】:对于那些感兴趣的人,根据迈克尔的回复,我们现在已经开始工作了
但是有一个问题。 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 主机添加 NTLM 支持?的主要内容,如果未能解决你的问题,请参考以下文章
如何为自己的WordPress站点安装SSL证书开启https访问
如何为我的 SQL 数据库添加远程主机以将其与我开发的应用程序连接