Oh, and after checking by AD...the field is "manager", and not "managedBy"...How wrong could I have been. doh!
Sorry about that.
the AD property "managedBy" is on a group object, and not a user one.
Woka
Printable View
Oh, and after checking by AD...the field is "manager", and not "managedBy"...How wrong could I have been. doh!
Sorry about that.
the AD property "managedBy" is on a group object, and not a user one.
Woka
Hello guys,
I don't know if this post still is live but first of all I would like to thank you all as I didn't know this is simple to use LDAP like this.
My code working great but my problem is that if I use a wrong password for existing username the user get locked.
How can I prevent this then I can just validate the username and password in the Active Directory.
Is there any way?
Cheers,
:thumb:
Just to let you know that I have used the first posted function in this section
cheers
Thanks for this code. It got me pass the first part of my little app, but now I need to know how to pass the AD credentials to another form. My app simply allows an Admin to login to the app and then run programs as an Admin like "RunAs" for common apps. Any advice on how to achieve this would be helpful.
thanks!
I am trying to use the OP code to find AD username. However, the only info available to me is Domain and ComputerName.
I've been searching for hours. Any ideas.
I have a few questions regarding the code the Original Poster provided.
1) Will the code work for Framework 2.0 and 3.5?
2) Is this the best code to use if one just wants to verify that the user does exist in Active Directory? The App that I am making will have its own security but at the least, they must be valid Domain Users.
3) My app will be an ASP.net app so would I be correct in assuming that I can use the same code?
Good morning,
1) Yes, the DirectoryServices code has not changed through the frameworks...each Framework does however add more functionality to DirectoryService.
2) Hmmmmm...not 100% sure. You could use The directory Searcher and just check if there is 1 result returned...or you can look into the DirectoryServices.AccountManagement namespace and play with the user object. http://msdn.microsoft.com/en-us/libr...anagement.aspx
3) This shouldn't be an issue...most of the AD coding I have done has been from an ASP.NET application.
Cheers,
Woka
I am not sure I follow. How can you search for a username that you don't know? :sQuote:
Originally Posted by CXXXV
Woka
Woka thanks for responding.
I get an invalid login and password each time even when I modify some of the code.
I don't have access to the Active Directory Server but I bet I have to drill down more than just one level as I bet they have everyone in groups and then in the group you can access the username.
That is just a guess but I have decided to go ahead and have my application have its own security and forget about AD.
If I am not mistaken, it sends the Username and Password in clear text over the Internet as well.
Thanks for the code.
I am able to obtain the computer name of the users of an .mdb via the JETSCHEMA built in to VB. However, what I need is to then search the AD using the computer name and return who is logged in to that computer.Quote:
Originally Posted by Wokawidget
AD cannot tell you who is logged on to a computer. WMI can however :)Quote:
Originally Posted by CXXXV
Here's an example vbscript:
Hope that helpsCode:strRemoteComputer = inputbox("Remote computer name:","Enter PC Name...")
if strRemoteComputer = "" then
wscript.echo "Click OK to close."
wscript.quit
end if
set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!//" & strRemoteComputer & "")
set colWin32 = objWMI.ExecQuery("Select * from Win32_ComputerSystem")
For Each objItem In colWin32
if strUsers <> "" then
strUser = strUser & ", " & objItem.UserName
else
strUser = objItem.UserName
End If
Next
if strUser = "" then
wscript.echo "Could not retrieve users from " & strRemoteComputer & ". Check that the machine is powered on and can access the network"
Else
wscript.echo strUser & " is logged on to " & strRemoteComputer
end if
Not if you use the Secure authentication type it doesnt (DirectoryServices.AuthenticationTypes.Secure)Quote:
Originally Posted by maikeru-sama
This post has been great! Thank you all for your time. I have a small issue. Here is my code:
This is my Auth.vb:
Here is my default.vb:Code:Imports System.DirectoryServices
Imports System.Net.Mail
Public Class Auth
Public Function AuthNow(ByVal userName As String, ByVal userPassword As String, ByVal groupname As String) As Boolean
Dim isValidated As Boolean = False
Dim domainName As String = "XXX.org"
Try
Dim ldapPath As String = "LDAP://" & domainName
Dim dirEntry As New DirectoryEntry(ldapPath, userName, userPassword, AuthenticationTypes.Secure)
Dim dirSearcher As New DirectorySearcher(dirEntry)
dirSearcher.Filter = "(SAMAccountName=" & userName & ")"
dirSearcher.PropertiesToLoad.Add("memberOf")
dirSearcher.PropertiesToLoad.Add("givenname")
dirSearcher.PropertiesToLoad.Add("managedBy")
Dim result As SearchResult = dirSearcher.FindOne()
Dim managerPath As String = String.Empty
If (result.Properties("managedBy").Count = 1) Then
Dim managerDN As String = result.Properties("managedBy").Item(0).ToString
managerPath = String.Format("LDAP://{0}", managerDN)
End If
If (managerPath.Length > 0) Then
Dim managerObject As DirectoryEntry = New DirectoryEntry(managerPath)
Dim managerUPN As String = managerObject.Properties("userPrincipalName").Value.ToString()
Dim managerDisplayName As String = managerUPN
If (managerObject.Properties("displayName").Count = 1) Then
managerDisplayName = managerObject.Properties("displayName").Value.ToString()
End If
End If
If Not result Is Nothing Then
If groupname.Length = 0 Then
isValidated = True
Else
Dim groupCount As Integer = result.Properties("memberOf").Count
Dim isInGroup As Boolean = False
For index As Integer = 0 To groupCount - 1
Dim groupDN As String = result.Properties("memberOf").Item(index)
Dim equalsIndex As Integer = groupDN.IndexOf("=")
Dim commaIndex As Integer = groupDN.IndexOf(",")
Dim group As String = groupDN.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1).ToLower
If group.Equals(groupname.ToLower) Then
isInGroup = True
Exit For
End If
Next index
isValidated = isInGroup
End If
End If
Catch ex As Exception
MsgBox("Bad Username or Password")
End Try
Return isValidated
End Function
End Class
My question is ... how do I get the manager's name to appear on default.vb?Code:Imports Auth
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim isauthenticated As Boolean = AuthenticateUser()
Dim managerDisplayName As String =
If isauthenticated Then
MsgBox("You have logged In!")
Else
MsgBox("You have not yet logged in!")
End If
End Sub
Private Function AuthenticateUser() As Boolean
Dim username As String = txtUsername.Text
Dim password As String = txtPassword.Text
Dim groupname As String = "IS"
Dim AuthSend As New Auth
Dim isAuthenticated As Boolean = AuthSend.AuthNow(username, password, groupname)
Return isAuthenticated
End Function
End Class
Thanks,
Richard
Well if you want to use the user object that you got from the manager part of the AuthNow function then you would have to return that user object (or just the name if thats all you are after) instead of just returning a boolean. Alternatively, you could just use a separate function to return the manager's name but only if the AuthNow function returns true.
If you want any further help then the best thing to do would be to create a new thread in the VB.NET part of these forums and put all the details in there, as the codebank threads such as this one arent really meant to be used for people just asking questions like yours :)
Chris is right. That question is not really related to AD code at all, and more geared towards general .NET code design.
Your AuthNow function needs to return the users AD object.
So in your code you would do:
You may want to create your own user class to return from this function, which holds properties of a user, instead of throwing AD DirectoryEntry objects around, that will lead to "cleaner" code.Code:DirectoryEntry authUser = AuthSend.AuthNow(username, password, groupname);
if(authUser != null)
{
//Authenticated
string managedBy = string.empty;
if(authUser.Properties["managedBy"].Value != null)
{
managedBy = authUser.Properties["managedBy"].Value.ToString();
}
}
else
{
//user failed authentication, do something here
}
Woka
Can this code be used in classic ASP? I've been asked to authenticate against AD in a classic ASP-coded page.
Just a note on the original code. If you use that code in any kind of loop the AD objects need to be disposed of because you'll leak lots of memory otherwise (speaking from personal experience):
Code:
Public Shared Function ValidateLogin(ByVal domain As String, ByVal username As String, ByVal password As String) As Boolean
Dim success As Boolean = False
Dim entry As New System.DirectoryServices.DirectoryEntry("LDAP://" & domain, username, password)
Dim searcher As New System.DirectoryServices.DirectorySearcher(entry)
searcher.SearchScope = DirectoryServices.SearchScope.OneLevel
Try
Dim results As System.DirectoryServices.SearchResult = searcher.FindOne
success = Not (results Is Nothing)
Catch ex As Exception
success = False
Finally
entry.Close() : entry.Dispose()
searcher.Dispose()
End Try
Return success
End Function
That is a good point :) but one minor comment - you don't need to call Close and Dispose on the DirectoryEntry object because they both do pretty much exactly the same thing. The Close method just calls an internal method named Unbind (which frees up the resources that were used) and the Dispose method calls the same Unbind method but then also calls MyBase.Dispose. So I would just go with Dispose on its own and not bother with Close :)
Hi guys. sorry to reawaken the thread...im using vb.net 2010 and i could really have good use for this code. im making an local domain chat application and the users should login with there domain acc/pw stored in the AD. so if someone could convert this code it would be appreciated.
There is no conversion required - this code works in .NET 2.0 so it will work in .NET 4.0 (which is what VS 2010 will target by default but you can just set it to target 2.0 if you want anyway).
Also, for anyone using .NET 3.5 or 4.0, you might want to look at the AccountManagement namespace which is new in .NET 3.5 - see here for more info and examples: http://msdn.microsoft.com/en-us/maga...135979.aspx#S9
this code:
gives this error list:vb Code:
Private Function ValidateActiveDirectoryLogin(ByVal Domain As String, ByVal Username As String, ByVal Password As String) As Boolean Dim Success As Boolean = False Dim Entry As New System.DirectoryServices.DirectoryEntry("LDAP://" & Domain, Username, Password) Dim Searcher As New System.DirectoryServices.DirectorySearcher(Entry) Searcher.SearchScope = DirectoryServices.SearchScope.OneLevel Try Dim Results As System.DirectoryServices.SearchResult = Searcher.FindOne Success = Not (Results Is Nothing) Catch Success = False End Try Return Success End Function
Error 1 Type 'System.DirectoryServices.DirectoryEntry' is not defined. C:\Users\karhol02\AppData\Local\Temporary Projects\IP chat with login\Login.vb 5 26 IP chat with login
Error 2 Type 'System.DirectoryServices.DirectorySearcher' is not defined. C:\Users\karhol02\AppData\Local\Temporary Projects\IP chat with login\Login.vb 6 29 IP chat with login
Error 3 'DirectoryServices' is not declared. It may be inaccessible due to its protection level. C:\Users\karhol02\AppData\Local\Temporary Projects\IP chat with login\Login.vb 7 32 IP chat with login
Error 4 Type 'System.DirectoryServices.SearchResult' is not defined. C:\Users\karhol02\AppData\Local\Temporary Projects\IP chat with login\Login.vb 9 28 IP chat with login
You need to add a reference to the System.DirectoryServices assembly
thanks its all working out now.
Just thought I'd add the following code change.
The Directory Service objects need to be disposed of:
vb Code:
Private Function ValidateActiveDirectoryLogin(ByVal domain As String, ByVal username As String, ByVal userPassword As String) As Boolean Dim success As Boolean = False Using rootEntry As New System.DirectoryServices.DirectoryEntry("LDAP://" & domain, username, userPassword) Using adSearcher As New System.DirectoryServices.DirectorySearcher(rootEntry) adSearcher.SearchScope = DirectoryServices.SearchScope.OneLevel Try Dim searchResults As System.DirectoryServices.SearchResult = adSearcher.FindOne success = Not (searchResults Is Nothing) Catch success = False End Try End Using End Using return success End Function
c# Code:
private bool ValidateActiveDirectoryLogin(string domain, string username, string userPassword) { bool success = false; using(System.DirectoryServices.DirectoryEntry rootEntry = New System.DirectoryServices.DirectoryEntry("LDAP://" & Domain, Username, Password)) { using(System.DirectoryServices.DirectorySearcher adSearcher = New System.DirectoryServices.DirectorySearcher(rootEntry)) { adSearcher.SearchScope = DirectoryServices.SearchScope.OneLevel; try { System.DirectoryServices.SearchResult searchResults = adSearcher.FindOne; success = (searchResults != null); } catch { success = false; } } } return success; }
Hope that helps.
Cheers, woka
There isn't really a need for the Success variable, you could just do this (I would also recommend using the Secure binding as I have done in the code below)
vb Code:
Private Function ValidateActiveDirectoryLogin(ByVal domain As String, ByVal username As String, ByVal userPassword As String) As Boolean Using rootEntry As New System.DirectoryServices.DirectoryEntry("LDAP://" & domain, username, userPassword, DirectoryServices.AuthenticationTypes.Secure) Using adSearcher As New System.DirectoryServices.DirectorySearcher(rootEntry) adSearcher.SearchScope = DirectoryServices.SearchScope.OneLevel Try Dim searchResults As System.DirectoryServices.SearchResult = adSearcher.FindOne Return Not searchResults Is Nothing Catch Return False End Try End Using End Using End Function
Again though, anyone using .NET 3.5 or 4.0 should probably just use the built in methods in the Sytem.DirectoryServices.AccountManagement namespace to do this.
I agree with the secure binding.
The AccountManagement namespace contains objects like Group and UserPrincipal...these are just wrappers around the DirectoryEntry object.
I prefer having the flexibility of using the DirectoryServices namespace and writing app specific wrappers.
One thing I personally disagree with is multiple return exit points from a function. I would strongly discourage this. This can lead to complex and hard to read code execution and the managability of your code decreases.
You gain no benefit by removing the bool success flag, only negatives, yet if you keep it then you have the flexibility for future code modifications and easy of reading the code.
cheers,
Woka
One example of this would be if I wanted to log the failure.
c# Code:
private bool ValidateActiveDirectoryLogin(string domain, string username, string userPassword) { bool success = false; using(System.DirectoryServices.DirectoryEntry rootEntry = New System.DirectoryServices.DirectoryEntry("LDAP://" & Domain, Username, Password)) { using(System.DirectoryServices.DirectorySearcher adSearcher = New System.DirectoryServices.DirectorySearcher(rootEntry)) { adSearcher.SearchScope = DirectoryServices.SearchScope.OneLevel; try { System.DirectoryServices.SearchResult searchResults = adSearcher.FindOne; success = (searchResults != null); } catch { success = false; } } } if(!success) { ErrorLogging.LogFailedLogin(username); } return success; }
If you had multiple exit points then you would have to write more code, a few lines per exit point, which is why it can become unmanagable very quickly.
Hope that helps.
WOka
lol surely if you wanted to log the failure you would log it in the Catch block so that you could actually get the exception details?
Anyway, I definitely agree that you get a lot more power and flexibility if you use the DirectoryEntry class etc but as this thread is purely about authenticating a user against AD I think it makes sense to suggest using classes/methods that are there purely to do this kind of thing.
Fine, this then:Quote:
One thing I personally disagree with is multiple return exit points from a function. I would strongly discourage this. This can lead to complex and hard to read code execution and the managability of your code decreases.
I just dont see the point declaring an extra variable when there is no real need for it :)vb Code:
Private Function ValidateActiveDirectoryLogin(ByVal domain As String, ByVal username As String, ByVal userPassword As String) As Boolean Using rootEntry As New System.DirectoryServices.DirectoryEntry("LDAP://" & domain, username, userPassword, DirectoryServices.AuthenticationTypes.Secure) Using adSearcher As New System.DirectoryServices.DirectorySearcher(rootEntry) adSearcher.SearchScope = DirectoryServices.SearchScope.OneLevel Dim searchResults As System.DirectoryServices.SearchResult Try searchResults = adSearcher.FindOne Catch searchResults = Nothing End Try Return Not searchResults Is Nothing End Using End Using End Function
Some examples of function that could return success or any other variable will not always have a try catch block.
I refer back to my last post about maintainability of multiple exit points.
I think there is a definate need for it.
Anyways, that's symantecs of coding, and should be taken up in another thread. Lets not get off track here :)
Woka
Sorry if this is a double post
Hey I would appreciate some help. I have implemented your active directory connect which works perfectly but I am trying to connect to a server and download or open a file for viewing. How can this be completed?
Doman: MyCompany.com
Server: ServerOne.MyCompany.com
path: \home\etc
file: Test.pdf
I have been using things like TransferFile but this option does not work when the site is deployed so I am thinking I am not using System.DirectoryServices correctly. Any tips, pointers, examples would be greatly appreciated.
Many Thanks
I have a web app using this Validate Login and it works great on an interal server. Now I need to move this to an external web server that allows AD authentication. Both of these servers are on Windows Server 2003 SP 2.
When I try to login to the external server it never authenticates. Besides changing the ldap domain for the exteranl server do I need to change anything else?
In the web.config on the internal server it has:
<authentication mode="Windows"></authentication>
<authorization>
<deny users="?"/>
</authorization>
On the external server I changed it to forms mode.
Thanks in advance.
Hi VbForums,
I am very happy to have found your site and this article dealing with what i am looking for a long time ... but for VBA.
Because I use Excel.
I have tried first to understand and adapt the code of all of your functions ... but without success.
Would it be possible for you to give me instructions to do that.
I need to give access to 10 of my colleagues to a workbook in which i have built one sheet for each of them.
We are ALL Authenticated users against our main AD Domain.
I want to display a userform in which each of them could enter its Username / Current AD Password ...
then ... send query to Validate these credentials and finally activate HIS PRIVATE SHEET ... each sheet name is username of my colleague.
Thanks in advance
Regards from PARIS.
Philou75
You need to start a thread on this topic in the Office Development forum. This thread hasn't been active for nine years, and is about working with a language that is radically different from VBA. Nothing in here is likely to be all that meaningful to the problem you have, but there are folks in Office Development who may well be able to answer the question you have.