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
经过数小时的研究和反复试验,以下是我最终做的事情:
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)
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 - 如果您在登录表单中使用Anti Forgery Token
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
此时,您将登录并可以访问User.Identity对象.您还可以使用[授权(Roles ="some_role")标记控制器和操作
事实证明,它比我想象的要容易,只是在这个主题上真的写得不多(至少我找不到任何东西).
此外,此代码假定您从可以访问网络上的域控制器的服务器运行应用程序.如果您使用的是DMZ服务器,则需要与网络管理员讨论此策略以获取其他选项.
我希望这能节省你一些时间.我也渴望听到社区对此的看法.也许有更好的方法来处理这种情况.如果是这样,请在此处分享.
谢谢.
Daniel D.
| 归档时间: |
|
| 查看次数: |
4331 次 |
| 最近记录: |