首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在现有的ASP.NET MVC 4.6Web项目中实现登录

在现有的ASP.NET MVC 4.6Web项目中实现登录
EN

Stack Overflow用户
提问于 2018-08-21 15:38:01
回答 3查看 21.9K关注 0票数 16

我必须用Active身份验证更改我的ASP.NET MVC + Knockout应用程序的现有(Windows)登录名。它由mvc控制器和webapi控制器组成。两人都必须经过认证。

我想通过切换到forms authentication并创建一个登录页面来做到这一点,当用户单击登录时,使用System.DirectoryServices.DirectoryEntry查询Active Directory。然后,其他进程,如更改密码、注册等,也将获得一个自定义html页面,并通过Active Directory上的System.DirectoryServices.DirectoryEntry执行它们的操作。

(也就是说,我找不到其他方法来做这件事,我确实找到了一些这样做的人,听起来和我以前见过的forms authentication__s一样。在这种情况下,用户/密码将不在数据库表中,而是在中。同样的想法,按活动目录交换数据库表)。

为了在一个全新的项目上看到这一点,我创建了一个新的ASP.NET MVC项目,并选择“work- or school acounts”(上面写着“用于使用活动目录对用户进行身份验证的应用程序),并选择”onPre前提“。不过,我必须提供这些项目:

  • 处所内主管当局
  • 应用程序Id url

我不知道该怎么办。我唯一拥有的是像ldap://etc.这样的活动目录url。

这是另一种/更新的/更好的方式来进行活动目录登录吗?或者唯一正确的(表单身份验证错误吗?)还是选错了?

我很困惑。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-08-26 08:23:24

可以使用以下方法在ASP.NET MVC中实现Active身份验证。

步骤1:修改AccountController中的登录方法,如下所示(还添加必要的引用):

代码语言:javascript
运行
复制
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    try
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        // Check if the User exists in LDAP
        if (Membership.GetUser(model.UserName) == null)
        {
            ModelState.AddModelError("", "Wrong username or password");
            return this.View(model);
        }

        ApplicationGroupManager groupManager = new ApplicationGroupManager();

        // Validate the user using LDAP 
        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            // FormsAuthentication.SetAuthCookie(model.UserName, false);

            // Check if the User exists in the ASP.NET Identity table (AspNetUsers)
            string userName = model.UserName.ToString().ToLower(new CultureInfo("en-US", false)); // When UserName is entered in uppercase containing "I", the user cannot be found in LDAP
            //ApplicationUser user = UserManager.FindByName(userName);
            ApplicationUser user = await UserManager.FindByNameAsync(userName); //Asynchronous method

            if (user == null) // If the User DOES NOT exists in the ASP.NET Identity table (AspNetUsers)
            {
                // Create a new user using the User data retrieved from LDAP
                // Create an array of properties that we would like and add them to the search object  
                string[] requiredProperties = new string[] { "samaccountname", "givenname", "sn", "mail", "physicalDeliveryOfficeName", "title" };
                var userInfo = CreateDirectoryEntry(model.UserName, requiredProperties);

                user = new ApplicationUser();

                // For more information about "User Attributes - Inside Active Directory" : http://www.kouti.com/tables/userattributes.htm
                user.UserName = userInfo.GetDirectoryEntry().Properties["samaccountname"].Value.ToString();
                user.Name = userInfo.GetDirectoryEntry().Properties["givenname"].Value.ToString();
                user.Surname = userInfo.GetDirectoryEntry().Properties["sn"].Value.ToString();
                user.Email = userInfo.GetDirectoryEntry().Properties["mail"].Value.ToString();
                user.EmailConfirmed = true;
                //user.PasswordHash = null;
                //user.Department = GetDepartmentId(userInfo.GetDirectoryEntry().Properties["physicalDeliveryOfficeName"].Value.ToString());

                //await Register(user);
                var result = await UserManager.CreateAsync(user); //Asynchronous method

                //If the User has succesfully been created
                //if (result.Succeeded)
                //{
                //    //var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                //    //var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                //    //await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>");
                //    //ViewBag.Link = callbackUrl;
                //    //return View("DisplayEmail");
                //}

                // Define user group (and roles)
                var defaultGroup = "751b30d7-80be-4b3e-bfdb-3ff8c13be05e"; // Id of the ApplicationGroup for the Default roles
                //groupManager.SetUserGroups(newUser.Id, new string[] { defaultGroup });
                await groupManager.SetUserGroupsAsync(user.Id, new string[] { defaultGroup }); //Asynchronous method
                //groupManager.SetGroupRoles(newGroup.Id, new string[] { role.Name });
            }
            // !!! THERE IS NO NEED TO ASSIGN ROLES AS IT IS ASSIGNED AUTOMATICALLY IN ASP.NET Identity 2.0
            //else // If the User exists in the ASP.NET Identity table (AspNetUsers)
            //{
            //    //##################### Some useful ASP.NET Identity 2.0 methods (for Info) #####################
            //    //ApplicationGroupManager gm = new ApplicationGroupManager();
            //    //string roleName = RoleManager.FindById("").Name; // Returns Role Name by using Role Id parameter
            //    //var userGroupRoles = gm.GetUserGroupRoles(""); // Returns Group Id and Role Id by using User Id parameter
            //    //var groupRoles = gm.GetGroupRoles(""); // Returns Group Roles by using Group Id parameter
            //    //string[] groupRoleNames = groupRoles.Select(p => p.Name).ToArray(); // Assing Group Role Names to a string array
            //    //###############################################################################################

            //    // Assign Default ApplicationGroupRoles to the User
            //    // As the default roles are already defined to the User after the first login to the system, there is no need to check if the role is NULL (otherwise it must be checked!!!)
            //    //var groupRoles = groupManager.GetGroupRoles("751b30d7-80be-4b3e-bfdb-3ff8c13be05e"); // Returns Group Roles by using Group Id parameter
            //    var groupRoles = await groupManager.GetGroupRolesAsync("751b30d7-80be-4b3e-bfdb-3ff8c13be05e"); // Returns Group Roles by using Group Id parameter (Asynchronous method)

            //    foreach (var role in groupRoles)
            //    {
            //        //Assign ApplicationGroupRoles to the User
            //        string roleName = RoleManager.FindById(role.Id).Name;
            //        UserManager.AddToRole(user.Id, roleName);
            //    }
            //}

            //Sign in the user
            await SignInAsync(user, model.RememberMe);

            if (this.Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
            {
                return this.Redirect(returnUrl);
                //return RedirectToLocal(returnUrl);
            }
            return this.RedirectToAction("Index", "Home");
        }
        else
        {
            ModelState.AddModelError("", "Wrong username or password");
            return this.View(model);
        }
    }
    catch (Exception ex)
    {
        TempData["ErrorMessage"] = ex.Message.ToString();
        return View("Error", TempData["ErrorMessage"]);
    }
}

/* Since ASP.NET Identity and OWIN Cookie Authentication are claims-based system, the framework requires the app to generate a ClaimsIdentity for the user. 
ClaimsIdentity has information about all the claims for the user, such as what roles the user belongs to. You can also add more claims for the user at this stage.
The highlighted code below in the SignInAsync method signs in the user by using the AuthenticationManager from OWIN and calling SignIn and passing in the ClaimsIdentity. */
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}

static SearchResult CreateDirectoryEntry(string sAMAccountName, string[] requiredProperties)
{
    DirectoryEntry ldapConnection = null;

    try
    {
        // Create LDAP connection object  
        //ldapConnection = new DirectoryEntry("alpha.company.com");
        ldapConnection = new DirectoryEntry("LDAP://OU=Company_Infrastructure, DC=company, DC=mydomain", "******", "******");
        //ldapConnection.Path = connectionPath;
        ldapConnection.AuthenticationType = AuthenticationTypes.Secure;

        DirectorySearcher search = new DirectorySearcher(ldapConnection);
        search.Filter = String.Format("(sAMAccountName={0})", sAMAccountName);

        foreach (String property in requiredProperties)
            search.PropertiesToLoad.Add(property);

        SearchResult result = search.FindOne();
        //SearchResultCollection searchResultCollection = search.FindAll();

        if (result != null)
        {
            //foreach (String property in requiredProperties)
            //    foreach (Object myCollection in result.Properties[property])
            //        Console.WriteLine(String.Format("{0,-20} : {1}",
            //                      property, myCollection.ToString()));
            // return searchResultCollection;
            return result;
        }
        else
        {
            return null;
            //Console.WriteLine("User not found!");
        }
        //return ldapConnection;
    }
    catch (Exception e)
    {
        Console.WriteLine("Exception caught:\n\n" + e.ToString());
    }
    return null;
}

注意:为了在LDAP身份验证中强制签名,在LogOff()方法中添加FormsAuthentication.SignOut()行,如下所示:

代码语言:javascript
运行
复制
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    AuthenticationManager.SignOut();
    FormsAuthentication.SignOut(); //In order to force logout in LDAP authentication
    return RedirectToAction("Login", "Account");
}

步骤2:更新您的LoginViewModel (或您的帐户模型类的名称),只包含这个LoginModel类:

代码语言:javascript
运行
复制
public class LoginViewModel
{
    [Required]
    public string UserName { get; set; }

    [Required]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }

    public bool RememberMe { get; set; }
}

另一方面,在必要的模型( ApplicationUserRegisterViewModel )中添加自定义属性,如名称、姓氏、ApplicationUser、部门等。

步骤3:最后,更新您的Web.config文件以包含以下元素:

代码语言:javascript
运行
复制
<connectionStrings>
  <!-- for LDAP -->
  <add name="ADConnectionString" connectionString="LDAP://**.**.***:000/DC=abc,DC=xyz" />
</connectionStrings>

<system.web>
  <!-- For LDAP -->
  <httpCookies httpOnlyCookies="true" />
  <authentication mode="Forms">
    <forms name=".ADAuthCookie" loginUrl="~/Account/Login" timeout="30" slidingExpiration="true" protection="All" />
  </authentication>
  <membership defaultProvider="ADMembershipProvider">
    <providers>
      <clear />
      <add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" connectionUsername="******" connectionPassword="******" />
    </providers>
  </membership>

  ...
</system.web>

更新:这里的是示例中使用的ApplicationUser类:

代码语言:javascript
运行
复制
// Must be expressed in terms of our custom Role and other types:
public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, 
    ApplicationUserRole, ApplicationUserClaim>, IUser<int>
{
    public string Name { get; set; }

    public string Surname { get; set; }
    
    public async Task<ClaimsIdentity>
        GenerateUserIdentityAsync(UserManager<ApplicationUser, int> manager)
    {
        var userIdentity = await manager
            .CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        return userIdentity;
    }
}

希望这能帮上忙。

票数 12
EN

Stack Overflow用户

发布于 2018-08-26 13:12:37

我在工作中使用过Active Directory Authetication。我用MVC创建了应用程序Windows Authetication,然后就完成了。应用程序自动显示带有域的AD登录。选择成员资格:[Authorize(Roles=@"DomainName\GroupName")] Ye可以在cmd: net用户名/domain中看到域和组,您不必使用LDAP

关于LDAP,请参阅:see here

票数 2
EN

Stack Overflow用户

发布于 2018-08-31 14:29:38

我有一个混合系统运行。来自数据库(外部用户)的用户与可以登录到我们系统的AD用户(内部用户)混合。为了与AD通信,我使用了一个名为LinqToLdap (https://github.com/madhatter22/LinqToLdap)的nuget包。这使用了LDAP协议,因此它也可以用于对Unix服务器进行身份验证。

这是身份验证方法

代码语言:javascript
运行
复制
public bool AuthenticateUser(string userName, string password)
    {
        InitConfig();
        using (var context = new DirectoryContext(_config))
        {
            var user = context.Query<LdapUserInfo>().FirstOrDefault(x => x.UserPrincipalName.Equals(userName));
            var dn = user?.DistinguishedName;
            if (string.IsNullOrWhiteSpace(dn))
                return false;

            using (var ldap = new LdapConnection(new LdapDirectoryIdentifier(_myConfig.Server)))
            {
                ldap.SessionOptions.ProtocolVersion = 3;

                ldap.AuthType = AuthType.Basic;
                ldap.Credential = _credentials;
                ldap.Bind();

                try
                {
                    ldap.AuthType = AuthType.Basic;
                    ldap.Bind(new NetworkCredential(dn, password));
                    return true;
                }
                catch (DirectoryOperationException)
                { }
                catch (LdapException)
                { }
            }

            return false;
        }
    }

    private void InitConfig()
    {
        if (_config != null)
            return;

        _config = new LdapConfiguration();
        _credentials = new NetworkCredential(_myConfig.Username, _myConfig.Password, _myConfig.Domain);
        _config.AddMapping(new AutoClassMap<LdapGroupInfo>(), _myConfig.NamingContext, new[] { "*" });
        _config.AddMapping(new AutoClassMap<LdapUserInfo>(), _myConfig.NamingContext, new[] { "*" });

        _config.ConfigureFactory(_myConfig.Server).AuthenticateAs(_credentials).AuthenticateBy(AuthType.Basic);
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51952214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档