使用 Windows 身份验证,定义 AD-Server

Using Windows Authentication, define AD-Server

我们正在开发一个网络应用程序,它允许我们编辑数据库中的数据。因为这个应用程序应该可以从外部访问,所以我们决定将它放在我们的一个 DMZ 服务器上。为了集中控制访问此服务的所有用户,我们决定使用 Windows 身份验证。但是由于 DMZ 服务器不是我们本地 LAN 中 Active Directory 的成员,因此这还不起作用(得到“401 - 未授权:由于凭据无效,访问被拒绝。”)。

我尝试像此处描述的那样指定 LDAP-ConnectionString ASP.NET MVC: How to setup web.config for LDAP authentication?。但它不起作用。我想,此配置并非设计用于 Windows 身份验证 (<authentication mode="Windows"/>)。即使我在本地机器上测试它并输入错误的凭据,它也会对我进行身份验证。所以我的猜测是,这个配置被完全忽略了。

<connectionStrings>
    <add name="ADConnectionString" connectionString="LDAP://<IP of AD-Server>/DC=<DomainName>"/>
</connectionStrings>
<system.web>
[...]
<authentication mode="Windows"/>
<authorization>
  <deny users="?" />
</authorization>
<membership defaultProvider="ADMembershipProvider" >
  <providers>
    <clear/>
    <add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" 
         connectionStringName="ADConnectionString"
         connectionUsername="<Domain>\<LDAP-Reader-User>"
         connectionPassword="<LDAP-Reader-Password>"/>
  </providers>
</membership>

为确保问题不在 LDAP 通信上,我进行了 LDAP 查询测试。 DMZ 服务器实际上能够发送 LDAP 查询。我测试了以下并得到了积极的结果(以及通过提供错误的密码而获得的消极结果)

public bool TestPrincipalContext()
{
    PrincipalContext c = new PrincipalContext(ContextType.Domain, "<IP of AD-Server>", "<LDAP-Reader-User>", "<LDAP-Reader-Password>");
    return c.ValidateCredentials(Request.Form["username"], Request.Form["password"]);
}

问题:

我正在寻找的是一个配置或 "custom-security-provider",我可以在其中指定 LDAP 服务器并使用 Windows 身份验证的所有内置功能。 这可能吗?我该怎么做?

免责声明

这可能对每个人都没有帮助,也可能不是最干净的方法,但它对我有所帮助。

为了解释我为什么选择这种方法,这里是情况:

  • 基本上我们只想检查给定用户是否有权访问某些元素,方法是检查他的 group-membership(通过使用 [Authorize]User.IsInRole)。并且我们希望在一个地方管理所有用户 (AD)

  • 我们的时间有限,不允许我们过多投资 很多时间来找到最好的方法。

  • 我们已经知道 AD-Server 我们将使用什么以及我们将如何对待有权访问上述服务的用户。另外,用户不能自己注册,所以总的来说我们可以控制谁可以访问我们的资源。

  • 我们希望将 运行 服务的数量保持在较低水平 因为 ADFS 对我们来说是一项附加服务,所以我们 搜索了替代品。

  • 由于"Security-Management"靠 关于 FormsAuthentication(Cookie 加密)我们认为是 安全的。我们还创建了一个具有有限权限的 service-user 只需阅读 LDAP。

如果您有安全问题、更好的解决方案或只是建议,请随时添加 comments/answers。

快速概览

我最终创建了一个自定义 "SecurityProvider"。我受到 https://support.microsoft.com/en-us/help/316748/how-to-authenticate-against-the-active-directory-by-using-forms-authen 的启发,它描述了使用 FormsAuthentication 和 .aspx 的身份验证。

基本上它在 Global.asax 中的 Application_AuthenticateRequest-Method 中设置用户 (HttpContext.User)。这是通过使用解密的 Cookie 完成的,该 Cookie 在 PrincipalContextFormsAuthentication.

的帮助下在登录中设置

自定义主体

由于 UserPrincipal 没有实现 IPrincipal,我制作了一个名为 CustomPrincipal 的包装器,它实现了 IPrincipal 并且有一个 UserPrincipal 作为 属性.这样我就可以从 PrincipalContext 中检索一个 UserPrincipal-object 并将其用作 User (HttpContext.User).

Application_AuthenticateRequest

在这里,我通过检查 cookie 来检查用户是否已登录,如果是, 解密 cookie 以获取用户名,创建所需的 CustomPrincipal-object 并将其设置为 User.

登录

登录时,它采用给定的用户名和密码,并使用 PrincipalContext 检查给定的凭据是否有效 (PrincipalContext.ValidateCredentials(username, password))。如果是,则会生成一个包含用户名的加密 cookie。

注销

注销只会让 "Auth"-Cookie 过期。就这么简单...