Blazor Server 应用程序的 Windows 身份验证 - 登录弹出窗口

5

我正在使用.NET 6.0.11构建Blazor Server应用,并使用Http.Sys进行部署。服务器和客户端都在同一个Windows域中。我希望根据用户的域登录授权,而不是构建与此应用程序特定的用户名/密码数据库和基础架构。

以下是在Program.cs中启用Windows身份验证的代码,基于官方文档中的代码:

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    builder.Services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);
    builder.WebHost.UseHttpSys(options =>
    {
        options.Authentication.Schemes =
            AuthenticationSchemes.NTLM | AuthenticationSchemes.Negotiate;            
        options.Authentication.AllowAnonymous = false;
    });
}

// ...
app.UseAuthentication();
app.UseAuthorization();

我使用ASP.NET Core Blazor身份验证和授权中的第一个代码示例查看身份验证状态。

如果我在http://localhost:55555上启动应用程序,那么页面会立即加载,并成功显示我的域和用户名。

但是,如果我将应用程序作为http://mycomputername.our.domain:55555启动,并在同一台机器上通过Chrome或Edge访问它,则会弹出一个要求输入用户名和密码的窗口:

Sign-in popup

注意:我曾经只运行了一次netsh http add urlacl url=....;这个命令是在更改启动URL后第一次运行时生成的异常消息建议的。

输入我的域登录用户名和密码被接受,并且之前的代码示例成功显示了我的用户名。我还注意到以下行为:

  • 设置AllowAnonymous = true;意味着它根本不会提示输入用户名/密码;页面只是以未经身份验证的用户继续。
  • 如果用户名/密码(针对域上的用户)输入不正确,则会立即生成HTTP错误401,它永远不会尝试执行Blazor默认错误页面。
  • 我希望认证是在客户端和域控制器之间进行的,而不是通过HTTP连接发送用户的密码!

我假设上述行为对于在访问此服务器的不同机器上使用其他域的用户也是相同的,尽管我还没有测试过。

我的问题:

  • 是否可以跳过用户名/密码弹出窗口,只获取已在客户端计算机上登录并进行访问的域用户?
  • (如果不行)将部署到IIS而不是Http.Sys是否会改变任何内容?

这个SO线程上似乎有基于Blazor的解决方案被讨论,但我不知道如何使用它们,因为弹出窗口总是在任何页面尝试渲染之前出现;如果登录失败,则会生成HTTP 401错误,并且不会执行任何Blazor页面。


注:由于文档指出Kestrel不支持Windows身份验证,我使用了HTTP.sys而非Kestrel;然而现在我使用Kestrel也可以工作了,同时结合被接受的答案中的信息--不确定那里的情况是什么。

也许它不喜欢使用http?您尝试安装证书并使用https了吗? - scotru
它是否可以在本地机器之外的连接中工作?我想知道这里建议的注册表更改“BackConnectionHostNames”是否有帮助?https://serverfault.com/questions/722722/windows-auth-in-iis-does-not-work-when-browsing-to-the-website-on-the-server-run - scotru
@scotru 是的 - 我已经尝试过使用安装为浏览器信任的自签名证书的HTTPS;行为是相同的。 - M.M
2个回答

3

这是一个客户端问题。

如果我在 http://localhost:55555 上启动应用程序,那么页面会立即加载,并成功显示我的域和用户名。

然而,如果我将应用程序作为 http://mycomputername.our.domain:55555 启动,并在同一台机器上使用 Chrome 或 Edge 访问它,则会弹出一个要求输入用户名和密码的窗口:

这是因为浏览器将 localhost 视为您的内部网络中的(相对可信的)服务器,但将 mycomputername.our.domain 视为(潜在敌对的)互联网服务。出于安全原因,Chrome 和 Edge 默认仅与您自己内部网络中的服务器使用 Windows 凭据。

为了确定 URL 属于哪个组,Chrome、Internet Explorer 和 Edge 使用 Windows 自己的“内部网络区域”设置。要添加您的 URL,请执行以下操作:

  • 在 Windows 开始菜单中搜索“Internet 选项”,然后
  • 导航到“安全性/本地 Intranet/站点/高级”。

如果您想使用非基于Chromium的浏览器进行测试,以下是如何配置Firefox。 Firefox管理其自己的URL列表,其中允许Windows身份验证:

我希望认证是在客户端和域控制器之间完成的,而不是通过HTTP连接发送用户密码!

如果客户端和服务器同意使用Kerberos,那么可以:客户端与域控制器通信以进行身份验证并获取服务票据,然后使用该票据访问您的服务。

如果他们不同意,则将使用NTLM。 在这种情况下,认证发生在客户端和您的服务器之间。 但是,NTLM也不会以明文形式发送您的密码,而是将其用作挑战-响应机制的一部分。


1
谢谢,做出那个更改完美地起作用了。(同时还注意到 trendmicro.com 被列为内部域,即使我们不再使用该产品...) - M.M

1
有可能跳过用户名/密码弹窗,只获取已在客户端机器上登录并执行访问的域用户吗?
在我的看法中,“Windows身份验证”无法做到这一点,因为您看到的弹出对话框是特殊的浏览器功能,可启用Windows身份验证。这是为了支持使用域身份验证的内部应用程序而创建的。我不知道任何访问该浏览器行为的方法。
如果不行,那么将部署到IIS而不是Http.Sys会改变什么吗?
我没有使用Http.Sys进行部署,但根据文档所述,它支持Windows身份验证。由于对于Http.Sys,您需要在代码中编写配置,因此部署方式会有所不同,与IIS不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接