Get an AD account password expiration time in .NET

xiaoxiao2021-03-06  37

original:

Http://www.blogcn.com/user8/flier_lu/blog/4371854.html

The .NET Framework provides a server for operating the LDAP interface for operating the AD, and we can easily implement the user account through the AD to verify the user account through this group, and the information to the AD query domain and its group. Integrate AD in web applications to implement one of the important means of realizing corporate single point landing.

The simple dog bears have a series of very well - published articles on its blog. This is the basic knowledge of this.

Active directory .NET programming TIPS

Use System.DirectoryServices.Protocols to implement simple operations for AD

Adhelper Active Directory User Operation Class

Although the example code he given is incomplete, it provides a good foundation for later people.

In order to let the author's SharePoint-based intranet portal to provide some convenient small features, if you queried your own account expiration time, the author has made some modifications to its package code, defined the Adserver / Adgroup / ADUser separately The relationship is clearer in the Package of the AD server / group / user. Looking back and other package code stably, and then write a detailed introduction.

Where a nasty question is how to get the password expiration time of the current account from the AD. For domain-based users, through the Winnt: // protocol of the ADSI interface, you can get this information from Iadsuser :: PasswordExpirationDate; but for the LDAP: // protocol interface of the AD, this field does not exist, you need us Handmade account expiration time (MaxPwdage) of the PWDLASTSET and the user's domain.

These commonly used properties are defined in the User object of the ADSI interface.

User Object Properties

Microsoft MSDN also specially has an article in detail how this calculation

How longal my password expiRes?

Its core algorithm step is as follows:

1. Has the account is disabled

2. Does the account password have been set?

3. Does the account area have a password period setting?

4. Calculate the number of days set in the password period

5. Calculate the password expiration time

The algorithm flow chart is as follows:

For VBScript only need a simple code to complete the task

The following program code is: On Error Resume NextConst ADS_UF_DONT_EXPIRE_PASSWD = & h10000Const E_ADS_PROPERTY_NOT_FOUND = & h8000500DConst ONE_HUNDRED_NANOSECOND = .000000100Const SECONDS_IN_DAY = 86400Set objADSystemInfo = CreateObject ( "ADSystemInfo" [img] /images/wink.gif [/ img] 'LINE 8Set objUser = GetObject ( "LDAP: //" & objADSystemInfo.UserName) 'LINE 9intUserAccountControl = objUser.Get ( "userAccountControl" [img] /images/wink.gif [/ img] If intUserAccountControl And ADS_UF_DONT_EXPIRE_PASSWD Then WScript.Echo "The password does not expire. "WScript.QuitElse dtmValue = objUser.PasswordLastChanged If Err.Number = E_ADS_PROPERTY_NOT_FOUND Then WScript.Echo" The password has never been set. "WScript.Quit Else intTimeInterval = Int (Now - dtmValue) WScript.Echo" The password was last set on "& _ DateValue (DTMValue) &" AT "& TimeValue (DTMValue) & Vbcrlf & _" The Difference Between When The Password Was Last "& VBCRLF & _ "Set and today is" & intTimeInterval & "days" End If Set objDomain = GetObject ( "LDAP: //" & objADSystemInfo.DomainDNSName) Set objMaxPwdAge = objDomain.Get ( "maxPwdAge" [img] /images/wink.gif [/ img] If objMaxPwdAge.LowPart = 0 Then WScript.Echo "The Maximum password Age is set to 0 in the" & _ "domain. Therefore, the password does not expire." WScript.Quit Else dblMaxPwdNano = _ Abs (objMaxPwdAge .Highpart * 2 ^ 32

objMaxPwdAge.LowPart) dblMaxPwdSecs = dblMaxPwdNano * ONE_HUNDRED_NANOSECOND dblMaxPwdDays = Int (dblMaxPwdSecs / SECONDS_IN_DAY) WScript.Echo "Maximum password age is" & dblMaxPwdDays & "days" If intTimeInterval> = dblMaxPwdDays Then WScript.Echo "The password has expired." Else WScript "The Password Will Expire ON" & _ DateValue (DTMValue DBLmaxpwdday) & "(" & _ INT (DTMValue DBLmaxpwddays) - & "Days from Today)." End if End IFend IF but because .NET The simple package of the Active Directory in V1.x makes the above functions in .NET is relatively cumbersome.

First, you need to get the value of the useerAccountControl field by the DirectoryEntry package encapsulated by the ADUser object, and determines if the password will never expire:

The following program code is: public class AdUser: AdItem {public enum ADS_USER_FLAG_ENUM {... ADS_UF_DONT_EXPIRE_PASSWD = 0X10000, ...} public int UserAccountControl {get {return Convert.ToInt32 (Properties [ "userAccountControl"] [0]);} } Public bool ispasswordnotexpire {get {return (useeraccountControl & (int) ads_user_flag_enum.ads_uf_dont_expire_passwd)! = 0;}}}

Then you need to access the password last reset time, it is determined whether the account is used.

It should be noted here that the password last reset time (PWDLASTSET) and domain password expiration time (MaxPwDage) are the Integer8 type in AD. Although theoretically corresponds to Long in C #, it is not accessible by System.DirectoryServices. That is to say, for these Integer8 types of fields, the forced conversion calls such as Convert.Toint 64 (Properties ["PWDLASTSET"] [0]) will be thrown directly.

To access this field, it must explicitly convert through the IadsLargeInteger interface in the ADSI specification.

An article on .NET 247 introduces this problem solution.

DirectoryEntry __comobject.

And the conversion code in this example may also overflow problems, need to be careful

Problem with the highpart and lowpart property Methods Complete conversion code as follows:

The following is the program code: public abstract class adentry: idisposable {// Access the integer8 type in .NET must via the IadsLargeinteger interface // http://www.dotnet247.com/247reference/msgs/31/159934.aspx [comImport] [Guid ( "9068270B-0939-11D1-8BE1-00C04FD8D503" [img] /images/wink.gif [/ img]] [InterfaceType (ComInterfaceType.InterfaceIsDual)] internal interface IADsLargeInteger {[DispId (0x00000002)] int HighPart {get (} [Dispid (0x00000003)] int lowpart {get; set;}} INTERNAL VALUE) {// must be carefully overflow before converting IADSLARGEINTEGER content to long, you must be careful // http://www.rlmueller.net /Integer8discussion.htm return ((Ulong) value.highpart << 32) (Ulong) value.lowpart);}}

Only in this problem can only be replaced on .NET:

The following program code is: public class AdUser: AdItem {// http://msdn.microsoft.com/library/en-us/dnclinic/html/scripting09102002.asp public DateTime PasswordExpirationDate {get {if (IsPasswordNotExpire) {return DateTime .Maxvalue; // account is set to password never expired} else {long lastchanged; try {lastchanged = getlongvalue ({}) ["pwdlastset"] [0]);} catch (exception) {return DateTime.MinValue; // The password is not set to} Iadslargeinteger maxage = (iadslargeinteger) server.properties ["maxpwdage"] [0]; if (maxage.lowpart == 0) Return DateTime.maxValue; // Domain Password No setting max period Else Return PasswordLastChanged.adddays (Server.MaxpasswordDays);}}}}

Although it is a small problem, the resistance in it can be not small.

Hope

转载请注明原文地址:https://www.9cbs.com/read-62310.html

New Post(0)