【问题标题】:How to get user's password expiration date from Active Directory?如何从 Active Directory 获取用户的密码到期日期?
【发布时间】:2017-04-06 09:21:51
【问题描述】:

我已经使用 LDAP 在 ASP.NET MVC 5 中实现了 Active Directory 身份验证。我想知道如何获取用户的

  1. 帐户已锁定(布尔值)
  2. 密码已过期(布尔值)
  3. 密码到期日期(日期时间)

这是我当前的代码:

using System.Web.Mvc;
using System.Web.Security;
using MvcApplication.Models;

[HttpPost]
public ActionResult Login(LoginModel model, string returnUrl)
{
    if (!this.ModelState.IsValid)
    {
        return this.View(model);
    }

    if (Membership.ValidateUser(model.UserName, model.Password))
    {
        FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

        if (this.Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
            && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
        {
            return this.Redirect(returnUrl);
        }

        return this.RedirectToAction("Index", "Home");
    }

    this.ModelState.AddModelError(string.Empty, "The user name or password provided is incorrect.");

    return this.View(model);
}

public ActionResult LogOff()
{
    FormsAuthentication.SignOut();

    return this.RedirectToAction("Index", "Home");
}

【问题讨论】:

  • 我希望尽可能多地使用 System.Web.Security。通过它,我能够检索 AccountLocked。现在我需要知道如何将我的 LDAP Activedirectory 实例化为一个对象,以便我可以获得它的对象属性。有人知道如何实现吗?

标签: c# asp.net asp.net-mvc active-directory


【解决方案1】:

【讨论】:

  • 我希望尽可能多地使用 System.Web.Security。通过它,我能够检索 AccountLocked。现在我需要知道如何将我的 LDAP Activedirectory 实例化为一个对象,以便我可以获得它的对象属性。有人知道如何实现吗?
  • 例如,我已经更改了答案并添加了链接。
  • 嘿,谢谢您的帮助。我设法用另一种方法解决了它。我已经上传了答案。你可以看看。
  • 很高兴你找到了答案。
【解决方案2】:

我设法使用 System.Web.Security 和 System.DirectoryServices 的组合来做到这一点。

public bool IsExpired(MembershipUser user, LoginModel model)
{
    bool result = false;

    string ldap = ConfigurationManager.ConnectionStrings["ADConnectionString"].ConnectionString;

    DirectoryEntry rootEntry = new DirectoryEntry(ldap, model.UserName, model.Password, AuthenticationTypes.Secure);

    DirectorySearcher mySearcher = new DirectorySearcher(rootEntry);

    SearchResultCollection results;
    string filter = "maxPwdAge=*";
    mySearcher.Filter = filter;

    results = mySearcher.FindAll();
    long maxDays = 0;
    if (results.Count >= 1)
    {
        Int64 maxPwdAge = (Int64)results[0].Properties["maxPwdAge"][0];
        maxDays = maxPwdAge / -864000000000;
    }

    long daysLeft = 0;

    daysLeft = maxDays - DateTime.Today.Subtract(user.LastPasswordChangedDate).Days;

    if (daysLeft <0)
    {
        result = true;
    } else
    {
        if (daysLeft<=14)
        {
            this.Expiring = true;
            this.ExpiringString = String.Format("You must change your password within" + " {0} days", daysLeft);
        }       
        else
        {
            this.Expiring = false;
        }     
    }

    return result;
}

【讨论】:

    【解决方案3】:

    这是获取用户帐户密码到期日期的另一种方法,从结果中您可以轻松计算 IsExpired:

    public static DateTime GetPasswordExpirationDate(UserPrincipal user)
    {
        DirectoryEntry deUser = (DirectoryEntry)user.GetUnderlyingObject();
        ActiveDs.IADsUser nativeDeUser = (ActiveDs.IADsUser)deUser.NativeObject;
        return nativeDeUser.PasswordExpirationDate;
    }
    

    您需要添加对通常位于 C:\Windows\System32\activeds.tlb 的 ActiveDS COM 库的引用。

    【讨论】:

      【解决方案4】:

      我从谷歌搜索到这里,发现当前的答案已经过时和/或繁琐(我不想导入 COM dll,如果可能的话,我想避免复杂的算术)。此外,似乎接受的答案没有考虑到可能生效的maxPwdAge 的更精细设置。

      我发现AD暴露了计算属性msDS-UserPasswordExpiryTimeComputed,可以直接使用,而不是进行复杂的计算:

      
      public DateTime? GetPasswordExpirationTime()
      {
        var path = @"ldap://yourserver";
        // null uses the current user's credentials.
        var user = "yourUserNameOrNull";
        var password = "yourPasswordOrNull";
        var idToSearch = "userNameToCheck";
        using(var entry = new DirectoryEntry(path, user, password, AuthenticationTypes.Secure))
        using(var ds = GetSearcher(entry, $"(sAMAccountName={idToSearch})"))
        {
          ds.PropertiesToLoad.Add("msDS-UserPasswordExpiryTimeComputed");
          var user = ds.FindOne();
          return DateTimePropertyFromLong(user, "msDS-UserPasswordExpiryTimeComputed")
        }
      }
      
      public static DateTime? DateTimePropertyFromLong(SearchResult sr, string propName)
      {
        if (!sr.Properties.Contains(propName)) return null;
        var value = (long) sr.Properties[propName][0];
        return value == long.MaxValue ? (DateTime?)null : DateTime.FromFileTimeUtc(value);
      }
      

      相关位只是PropertiesToLoad.Add("msDS-UserPasswordExpiryTimeComputed")和AD通过DateTime.FromFileTimeUtc方法返回的奇怪长格式的转换。

      【讨论】:

        猜你喜欢
        • 2016-04-09
        • 1970-01-01
        • 1970-01-01
        • 2017-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多