具有 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认证授权。因此我的困境。
非常感谢任何建议。
谢谢。
经过数小时的研究和反复试验,这就是我最终做的事情:
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
进行身份验证
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;
}
Global.asax - 如果您在登录表单中使用防伪令牌
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
此时,您将登录并可以访问 User.Identity 对象。您还可以使用 [Authorize(Roles = "some_role"]
标记控制器和操作
事实证明这比我想象的要容易,只是关于这个主题的真正写的不多(至少我找不到任何东西)。
此外,此代码假定您是 运行 来自服务器的应用程序,该服务器可以访问您网络上的域控制器。如果您在 DMZ 服务器上,则需要与您的网络管理员讨论此策略以获得其他选项。
希望这能为您节省一些时间。我也很想知道社区对此有何看法。也许有更好的方法来处理这种情况。如果是这样,请在这里分享。
谢谢。
丹尼尔·D.
这是我的场景。我有一个使用 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认证授权。因此我的困境。
非常感谢任何建议。
谢谢。
经过数小时的研究和反复试验,这就是我最终做的事情:
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
进行身份验证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; }
Global.asax - 如果您在登录表单中使用防伪令牌
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
此时,您将登录并可以访问 User.Identity 对象。您还可以使用 [Authorize(Roles = "some_role"]
标记控制器和操作事实证明这比我想象的要容易,只是关于这个主题的真正写的不多(至少我找不到任何东西)。
此外,此代码假定您是 运行 来自服务器的应用程序,该服务器可以访问您网络上的域控制器。如果您在 DMZ 服务器上,则需要与您的网络管理员讨论此策略以获得其他选项。
希望这能为您节省一些时间。我也很想知道社区对此有何看法。也许有更好的方法来处理这种情况。如果是这样,请在这里分享。
谢谢。
丹尼尔·D.