Asp.net mvc 5 带LDAP身份验证的OWIN

Asp.net mvc 5 带LDAP身份验证的OWIN,asp.net-mvc-5,ldap,owin,Asp.net Mvc 5,Ldap,Owin,这是我的设想。我有一个MVC5应用程序,它使用Owin作为身份验证机制。默认模板在登录操作中调用SignInManager.PasswordSignInAsync,我希望覆盖该操作以使用LDAP验证用户,而不是查看数据库 我可以通过以下方式进行验证: PrincipalContext dc = new PrincipalContext(ContextType.Domain, "domain.com", "DC=domain,DC=com", "user_name", "password");

这是我的设想。我有一个MVC5应用程序,它使用Owin作为身份验证机制。默认模板在登录操作中调用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身份验证。该应用程序将从网络外部访问,但要求使用广告认证和授权。这就是我的困境

非常感谢您的任何建议


谢谢。

经过数小时的研究和反复试验,我终于做到了:

  • 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);
                }
    
  • IdentityConfig.cs(CheckPasswordAsync)根据LDAP进行身份验证

    AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 公共覆盖异步任务CheckPasswordAsync(应用程序用户,字符串密码) { PrincipalContext dc=新PrincipalContext(ContextType.Domain,“Domain”,“dc=Domain,dc=com”,“用户名],[密码]); bool authenticated=dc.ValidateCredentials(user.UserName,password); 返回认证; }
  • Global.asax-如果您在登录表单中使用防伪令牌

  • AntiForgeryConfig.UniqueClaimTypeIdentifier=ClaimTypes.NameIdentifier; 此时,您将登录并可以访问User.Identity对象。您还可以使用[Authorize(Roles=“some_role”]

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

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

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

    谢谢


    Daniel D.

    要创建PrincipalContext实例,[用户名]和[密码]将来自被授予查询LDAP权限的帐户?正确。此帐户必须能够在LDAP中查找用户。这太棒了!非常感谢。我花了几个小时在MVC中搜索LDAP身份验证的最佳选项。你是个救命恩人!谢谢。很高兴我能帮上忙:) AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;