使用LDAP身份验证的OWIN

dpd*_*nev 6 ldap owin asp.net-mvc-5

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

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

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

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

UserPrincipal user = UserPrincipal.FindByIdentity(dc, IdentityType.SamAccountName, userName);
Run Code Online (Sandbox Code Playgroud)

但是,我被困在这里,我不知道如何继续签署用户.我的目标是在我登录用户之后,我可以访问User.Identity,包括用户所在的所有角色.实际上,应用程序的行为应该像使用Windows身份验证一样,但凭据由用户提供登录页面.

您可能会问为什么不直接使用Windows身份验证.该应用程序将从网络外部访问,但要求是使用AD身份验证和授权.因此我的困境.

任何建议都非常感谢.

谢谢.

dpd*_*nev 10

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

  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);
                }
    
    Run Code Online (Sandbox Code Playgroud)
  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 - 如果您在登录表单中使用Anti Forgery Token

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

此时,您将登录并可以访问User.Identity对象.您还可以使用[授权(Roles ="some_role")标记控制器和操作

事实证明,它比我想象的要容易,只是在这个主题上真的写得不多(至少我找不到任何东西).

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

我希望这能节省你一些时间.我也渴望听到社区对此的看法.也许有更好的方法来处理这种情况.如果是这样,请在此处分享.

谢谢.

Daniel D.