带有 LDAP 身份验证的 OWIN [英] OWIN with LDAP Authentication

查看:28
本文介绍了带有 LDAP 身份验证的 OWIN的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

PrincipalContext dc = new PrincipalContext(ContextType.Domain, "domain.com", "DC=domain,DC=com", "user_name", "password");bool 认证 = dc.ValidateCredentials(用户名,密码);

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

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

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

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

非常感谢任何建议.

谢谢.

解决方案

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

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

    <上一页>ApplicationUser usr = new ApplicationUser() { UserName = model.Email };bool auth = await UserManager.CheckPasswordAsync(usr, model.Password);如果(授权){列表声明 = new List();

     foreach(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(新的 AuthenticationProperties(){AllowRefresh = true,IsPersistent = 假,ExpiresUtc = DateTime.UtcNow.AddDays(7),}, ci);返回重定向到本地(returnUrl);}别的{ModelState.AddModelError("", "无效的登录凭据.");返回视图(模型);}

  2. IdentityConfig.cs (CheckPasswordAsync) - 针对 LDAP 进行身份验证

    <上一页>公共覆盖异步任务 CheckPasswordAsync(ApplicationUser 用户,字符串密码){PrincipalContext dc = new PrincipalContext(ContextType.Domain, "domain", "DC=domain,DC=com", [user_name], [password]);bool 认证 = dc.ValidateCredentials(user.UserName, password);返回认证;}

  3. Global.asax - 如果您在登录表单中使用防伪令牌

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

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

标记控制器和操作

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

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

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

谢谢.

丹尼尔 D.

Here is my scenario. I have an MVC 5 application that uses Owin as an authentication mechanism. The default template calls the SignInManager.PasswordSignInAsync in the Login action which I would like to overwrite to use LDAP to validate the user instead of looking into the database.

I am able to do the validation via:

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

Then I can retrieve the UserPrincipal using:

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

However, I am stuck here and I am not sure how to continue with signing in the user. The goal is that after I sign in the user, I would have access to User.Identity including all the roles the user is in. Essentially, the app should behave as if it uses Windows Authentication, but the credentials are provided by the user on the Login page.

You would probably ask why not user Windows Authentication directly. The app will be accessed from the outside of the network, but the requirements are to use AD authentication and authorization. Hence my predicament.

Any suggestions are highly appreciated.

Thank you.

解决方案

After many hours of research and trial and error, here is what I ended up doing:

  1. AccountController.cs - Create the application user and sign in

        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) - Authenticate against 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 - if you are using the Anti Forgery Token in your login form

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

At this point, you will are logged in and can access the User.Identity object. You can also mark controllers and actions with [Authorize(Roles = "some_role"]

It turned out that it was easier than I thought, it is just that not much is really written on the topic (at least I could not find anything).

Also, this code presumes that you are running the app from a server which has access to the Domain Controller on your network. If you are on a DMZ server, you need to discuss this strategy with your network admin for other options.

I hope this saves you some time. I am also eager to hear what the community thinks of this. Maybe there is a better way of handling this situation. If so, please share it here.

Thanks.

Daniel D.

这篇关于带有 LDAP 身份验证的 OWIN的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆