2011-08-30 117 views
3

在Visual Basic中有没有一种方法来检查用户的密码是否设置为永不过期在Active Directory中?Active Directory - 检查密码是否永不过期?

我发现了一种方法来查找它的最后更改日期,但我找不到其他可用选项。

Dim de As DirectoryServices.DirectoryEntry = GetUser(uDetails.username) 
Dim objUser = GetObject(de.Path) 
If objUser.PasswordLastChanged < DateTime.Now.AddMonths(-3) Then 
... 

我在哪里可以找到所有可用objUser属性的列表?

回答

1
public bool isPasswordExpired(String p_UserName, String p_DomainName) 
{ 
    bool m_Check=false; 

    int m_Val1 = (int)de1.Properties["userAccountControl"].Value; 
    int m_Val2 = (int) 0x10000; 

    if (Convert.ToBoolean(m_Val1 & m_Val2)) 
    { 
     m_Check = true; 
    } //end 

    return m_Check 
} 
5

如果您使用.NET 3.5或更高版本,则应检查System.DirectoryServices.AccountManagement(S.DS.AM)命名空间。在这里阅读全部内容:

基本上,你可以定义域范围内,并可以轻松地查找用户和/或组AD:

// set up domain context 
PrincipalContext ctx = new PrincipalContext(ContextType.Domain); 

// find a user 
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName"); 

if(user != null) 
{ 
    // one of the properties exposed is "PasswordNeverExpires" (bool) 
    if(user.PasswordNeverExpires) 
    { 
     // do something here....  
     ... 
    } 
} 

的新的S.DS.AM可以很容易地与AD中的用户和群组玩耍!

+0

遗憾的是我在2 :( –

+0

@xrum:很好的理由,并约时间** **升级其 –

+0

不是我的决定:( –

1

你可以使用下面的代码最初是从here,我已经从C#转换,并根据您的问题,修改一点点(增加一个getter):

Dim pwdNeverExpires = getPasswordNeverExpires("Tim") 
setPasswordNeverExpires("Tim", True) 

' See http://msdn.microsoft.com/en-us/library/aa772300(VS.85).aspx 
<Flags()> _ 
Private Enum ADS_USER_FLAG_ENUM 
    ADS_UF_SCRIPT = 1 
    ' 0x1 
    ADS_UF_ACCOUNTDISABLE = 2 
    ' 0x2 
    ADS_UF_HOMEDIR_REQUIRED = 8 
    ' 0x8 
    ADS_UF_LOCKOUT = 16 
    ' 0x10 
    ADS_UF_PASSWD_NOTREQD = 32 
    ' 0x20 
    ADS_UF_PASSWD_CANT_CHANGE = 64 
    ' 0x40 
    ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 128 
    ' 0x80 
    ADS_UF_TEMP_DUPLICATE_ACCOUNT = 256 
    ' 0x100 
    ADS_UF_NORMAL_ACCOUNT = 512 
    ' 0x200 
    ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 2048 
    ' 0x800 
    ADS_UF_WORKSTATION_TRUST_ACCOUNT = 4096 
    ' 0x1000 
    ADS_UF_SERVER_TRUST_ACCOUNT = 8192 
    ' 0x2000 
    ADS_UF_DONT_EXPIRE_PASSWD = 65536 
    ' 0x10000 
    ADS_UF_MNS_LOGON_ACCOUNT = 131072 
    ' 0x20000 
    ADS_UF_SMARTCARD_REQUIRED = 262144 
    ' 0x40000 
    ADS_UF_TRUSTED_FOR_DELEGATION = 524288 
    ' 0x80000 
    ADS_UF_NOT_DELEGATED = 1048576 
    ' 0x100000 
    ADS_UF_USE_DES_KEY_ONLY = 2097152 
    ' 0x200000 
    ADS_UF_DONT_REQUIRE_PREAUTH = 4194304 
    ' 0x400000 
    ADS_UF_PASSWORD_EXPIRED = 8388608 
    ' 0x800000 
    ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 16777216 
    ' 0x1000000 
End Enum 

Protected Overridable Function getPasswordNeverExpires(ByVal userName As String) As Boolean 
    Const userNameString As String = "userName" 
    Const userFlagsString As String = "userFlags" 

    Dim machineName As String = Environment.MachineName 

    Dim userInThisComputerDirectoryEntry As DirectoryEntry = getUserInThisComputerDirectoryEntry(machineName, userName) 
    If userInThisComputerDirectoryEntry Is Nothing Then 
     Throw New ArgumentException("not found in " & machineName, userNameString) 
    End If 

    Dim userFlagsProperties As PropertyValueCollection = userInThisComputerDirectoryEntry.Properties(userFlagsString) 
    Dim userFlags As ADS_USER_FLAG_ENUM = CType(userFlagsProperties.Value, ADS_USER_FLAG_ENUM) 

    Return userFlags = (userFlags Or ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD) 
End Function 

Protected Overridable Sub setPasswordNeverExpires(ByVal userName As String, ByVal passwordNeverExpires As Boolean) 
    Const userNameString As String = "userName" 
    Const userFlagsString As String = "userFlags" 

    Dim machineName As String = Environment.MachineName 

    Dim userInThisComputerDirectoryEntry As DirectoryEntry = getUserInThisComputerDirectoryEntry(machineName, userName) 
    If userInThisComputerDirectoryEntry Is Nothing Then 
     Throw New ArgumentException("not found in " & machineName, userNameString) 
    End If 

    Dim userFlagsProperties As PropertyValueCollection = userInThisComputerDirectoryEntry.Properties(userFlagsString) 

    Dim userFlags As ADS_USER_FLAG_ENUM = CType(userFlagsProperties.Value, ADS_USER_FLAG_ENUM) 
    Dim newUserFlags As ADS_USER_FLAG_ENUM = userFlags 

    If passwordNeverExpires Then 
     newUserFlags = newUserFlags Or ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD 
    Else 
     newUserFlags = newUserFlags And (Not ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD) 
    End If 

    userFlagsProperties.Value = newUserFlags 

    userInThisComputerDirectoryEntry.CommitChanges() 
End Sub 

Protected Overridable Function getUserInThisComputerDirectoryEntry(ByVal machineName As String, ByVal userName As String) As DirectoryEntry 
    Dim computerDirectoryEntry As DirectoryEntry = getComputerDirectoryEntry(machineName) 

    Const userSchemaClassName As String = "user" 
    Return computerDirectoryEntry.Children.Find(userName, userSchemaClassName) 
End Function 

Protected Overridable Function getComputerDirectoryEntry(ByVal machineName As String) As DirectoryEntry 
    'Initiate DirectoryEntry Class To Connect Through WINNT Protocol 
    ' see: http://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.path.aspx 
    Const pathUsingWinNTComputerMask As String = "WinNT://{0},computer" 
    Dim path As String = String.Format(pathUsingWinNTComputerMask, machineName) 
    Dim thisComputerDirectoryEntry As New DirectoryEntry(path) 
    Return thisComputerDirectoryEntry 
End Function 

你必须添加引用System.DirectoryServices 。我已经在Windows Server 2008上使用.NET Framework 4(它也应该在2.0以下)进行了测试,没有使用Active Directory。但请自行检查并随意扩展以获取/设置其他属性或连接到其他机器(SomeDomain/OtherComputerName而不是Environment.MachineName)。

+0

咬伤我已经改变了这个设置!在服务器上测试上述方法。这就是为什么今天有些任务未能以错误值2147943730开始,因为我需要更新我的密码^^ –

2

对于.NET 2.0您可以使用一些LDAP。神奇的部分是userAccountControl:1.2.840.113556.1.4.803:=65536。第一部分是您要搜索的属性,第二部分表示“按位与”,第三部分表示检查的按位标志,在本例中为第17位。您可以在How to query Active Directory by using a bitwise filter中查看有关Active Directory中按位AND和OR的更多信息。

在下面的代码中更新SearchRoot变量与您的domain controller(DC)和FQDN

Imports System.DirectoryServices 

Public Class Form1 

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load 
     ''//Bind to the root of our domain 
     ''// YOU_DOMAIN_CONTROLLER should be one of your DCs 
     ''// EXAMPLE and COM are the parts of your FQDN 
     Dim SearchRoot As DirectoryEntry = New DirectoryEntry("LDAP://YOUR_DOMAIN_CONTROLLER/dc=EXAMPLE,dc=COM") 

     ''//Create a searcher bound to the root 
     Dim Searcher As DirectorySearcher = New DirectorySearcher(SearchRoot) 

     ''//Set our filer. The last part is dumb but that is the way that LDAP was built. 
     ''//It basically does a bitwise AND looking for the 17th bit to be set on that property "userAccountControl" which is the "password never expires" bit 
     ''//See this if you care to learn more http://support.microsoft.com/kb/269181 
     Searcher.Filter = "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))" 
     ''//Find all of the results 

     Dim Results = Searcher.FindAll() 
     Dim DE As DirectoryEntry 

     ''//Loop through each result 
     For Each R As SearchResult In Results 

      ''//Get the result as a DirectoryEntry object 
      DE = R.GetDirectoryEntry() 

      ''//Output the object name 
      Console.WriteLine(DE.Name) 
     Next 
    End Sub 

End Class 
相关问题