具有 LDAP 身份验证的 OWIN

OWIN with LDAP Authentication

这是我的场景。我有一个使用 Owin 作为身份验证机制的 MVC 5 应用程序。默认模板在登录操作中调用 SignInManager.PasswordSignInAsync,我想覆盖它以使用 LDAP 来验证用户而不是查看数据库。

我可以通过以下方式进行验证:

PrincipalContext dc = new PrincipalContext(ContextType.Domain, "domain.com", "DC=domain,DC=com", "user_name", "password");
        bool authenticated = dc.ValidateCredentials(userName, password);

然后我可以使用以下方法检索 UserPrincipal:

UserPrincipal user = UserPrincipal.FindByIdentity(dc, IdentityType.SamAccountName, userName);

但是,我被困在这里,我不确定如何继续登录用户。目标是在我登录用户后,我将有权访问 User.Identity,包括用户所处的所有角色。本质上,该应用程序的行为应该就像它使用 Windows 身份验证一样,但凭据由用户在登录页面上提供。

您可能会问为什么不直接使用用户 Windows 身份验证。 App会被外网访问,但是要求是使用AD认证授权。因此我的困境。

非常感谢任何建议。

谢谢。

经过数小时的研究和反复试验,这就是我最终做的事情:

  1. AccountController.cs - 创建应用程序用户并登录

        ApplicationUser usr = new ApplicationUser() { UserName = model.Email };
        bool auth = await UserManager.CheckPasswordAsync(usr, model.Password);
        if (auth)
                    {
                        List claims = new List();
    
    
                foreach (var group in Request.LogonUserIdentity.Groups)
                {
                    string role = new SecurityIdentifier(group.Value).Translate(typeof(NTAccount)).Value;
                    string clean = role.Substring(role.IndexOf("\") + 1, role.Length - (role.IndexOf("\") + 1));
                    claims.Add(new Claim(ClaimTypes.Role, clean));
                }
                claims.Add(new Claim(ClaimTypes.NameIdentifier, model.Email));
                claims.Add(new Claim(ClaimTypes.Name, model.Email));
                ClaimsIdentity ci = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
                 AuthenticationManager.SignIn(new AuthenticationProperties()
                 {
                     AllowRefresh = true,
                     IsPersistent = false,
                     ExpiresUtc = DateTime.UtcNow.AddDays(7),
                 }, ci);
                 return RedirectToLocal(returnUrl);
                }
                else
                {
                    ModelState.AddModelError("", "Invalid login credentials.");
                    return View(model);
                }
    
  2. IdentityConfig.cs (CheckPasswordAsync) - 针对 LDAP

    进行身份验证
    public override async Task CheckPasswordAsync(ApplicationUser user, string password)
            {
                PrincipalContext dc = new PrincipalContext(ContextType.Domain, "domain", "DC=domain,DC=com", [user_name], [password]);
                bool authenticated = dc.ValidateCredentials(user.UserName, password);
                return authenticated;
            }
    
  3. Global.asax - 如果您在登录表单中使用防伪令牌

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

此时,您将登录并可以访问 User.Identity 对象。您还可以使用 [Authorize(Roles = "some_role"]

标记控制器和操作

事实证明这比我想象的要容易,只是关于这个主题的真正写的不多(至少我找不到任何东西)。

此外,此代码假定您是 运行 来自服务器的应用程序,该服务器可以访问您网络上的域控制器。如果您在 DMZ 服务器上,则需要与您的网络管理员讨论此策略以获得其他选项。

希望这能为您节省一些时间。我也很想知道社区对此有何看法。也许有更好的方法来处理这种情况。如果是这样,请在这里分享。

谢谢。

丹尼尔·D.