Ask a Question related to ASP.NET Security, Design and Development.
-
Jon Delano #1
VB.NET LDAP Class
Hello
After some effort I was able to come up with this class (converted from a C#
example on MS' web site).
Put this in a class in you vb.net web project and you should be able to
authenticate a user against active directory and also retrieve their user
groups.
You must replace the LDAP://yourdomain with the actual domain that you'd
like to authenticate against.
Please do with this as you will (and use at your own risk):
Imports System.DirectoryServices
Imports System.Runtime.InteropServices
Imports System.Globalization
Public Class ADAuthenticate
Private _path As String
Private _filterAttribute As String
Private _UserFirstName As String
Private _UserLastName As String
Private _UserPath As String
Private _AuthenticationErrorString As String
Public Function IsAuthenticated(ByVal UserName As String, ByVal Password
As String) As Boolean
' authenticate the user and get some info about them
Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
Password, System.DirectoryServices.AuthenticationTypes.Secur e)
Dim ds As New DirectorySearcher(entry)
Dim myFilter As String = "(&(objectClass=user)(samaccountname=" +
UserName + "))"
ds.Filter = myFilter
ds.PropertiesToLoad.Add("sn")
ds.PropertiesToLoad.Add("GivenName")
Try
Dim sRslt As SearchResult = ds.FindOne
If sRslt Is Nothing Then
Return False
Else
_filterAttribute = UserName
Dim propName As String
Dim value As Object
For Each propName In sRslt.Properties.PropertyNames
For Each value In sRslt.Properties(propName)
If propName = "sn" Then
_UserLastName = value
End If
If propName = "givenname" Then
_UserFirstName = value
End If
If propName = "adspath" Then
_UserPath = value
End If
Next value
Next propName
Return True
End If
sRslt = Nothing
ds = Nothing
Catch ex As Exception
_AuthenticationErrorString = ex.Message & "<br>" & ex.StackTrace
Return False
Finally
entry.Dispose()
entry = Nothing
ds.Dispose()
ds = Nothing
End Try
End Function
Public ReadOnly Property LdapAuthenticationErrorString() As String
Get
Return _AuthenticationErrorString
End Get
End Property
Public ReadOnly Property LdapUserFirstName() As String
Get
Return _UserFirstName
End Get
End Property
Public ReadOnly Property LdapUserLastName() As String
Get
Return _UserLastName
End Get
End Property
Public Function GetUserGroups(ByVal UserName As String, ByVal Password
As String) As String
' get the groups the user belongs to
Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
Password, System.DirectoryServices.AuthenticationTypes.Secur e)
Dim search = New DirectorySearcher(entry)
search.Filter = "(&(objectClass=user)(cn=" + _filterAttribute + "))"
search.PropertiesToLoad.Add("memberOf")
Dim groupNames As New System.Text.StringBuilder()
Try
Dim result As SearchResult = search.FindOne()
Dim propertyCount As Int32 = result.Properties("memberOf").Count
Dim dn As String
Dim equalsIndex As Int32, commaIndex As Int32
Dim propertyCounter As Int32
For propertyCounter = 0 To propertyCount - 1
dn = result.Properties("memberOf")(propertyCounter)
equalsIndex = dn.IndexOf("=", 1)
commaIndex = dn.IndexOf(",", 1)
If (-1 = equalsIndex) Then
groupNames.Append(dn)
Else
groupNames.Append(dn.Substring((equalsIndex + 1),
(commaIndex - equalsIndex) - 1))
groupNames.Append("|")
End If
Next propertyCounter
Catch ex As Exception
Throw New Exception("Error obtaining group names. " +
ex.Message)
Finally
entry.Dispose()
entry = Nothing
search = Nothing
End Try
Return groupNames.ToString()
End Function
End Class
Good luck
Jon
Jon Delano Guest
-
#25580 [WFx]: set_error_handler to a class/method resets class properties when error occurs
ID: 25580 Updated by: sniper@php.net Reported By: paul dot liversidge at recycledpixels dot com Status: Wont... -
#25580 [Opn->WFx]: set_error_handler to a class/method resets class properties when error occurs
ID: 25580 Updated by: sniper@php.net Reported By: paul dot liversidge at recycledpixels dot com -Status: Open... -
#25580 [Opn]: set_error_handler to a class/method resets class properties when error occurs
ID: 25580 User updated by: paul.liversidge@recycledpixels.com Reported By: paul dot liversidge at recycledpixels dot com... -
#25580 [NEW]: set_error_handler to a class/method resets class properties when error occurs
From: paul dot liversidge at recycledpixels dot com Operating system: Windows XP PHP version: 4.3.2 PHP Bug Type: ... -
#23038 [Com]: PHP does not detect parent class inside child class' constructor
ID: 23038 Comment by: hewei at ied dot org dot cn Reported By: black at sunshine dot krneki dot org Status: ... -
Raterus #2
Re: VB.NET LDAP Class
I hope you didn't spend too long converting this.. :-)
[url]http://support.microsoft.com/default.aspx?scid=kb;EN-US;326340[/url]
"Jon Delano" <jd31068@hotmail.com> wrote in message news:94cOc.209721$Oq2.196851@attbi_s52...> Hello
>
> After some effort I was able to come up with this class (converted from a C#
> example on MS' web site).
> Put this in a class in you vb.net web project and you should be able to
> authenticate a user against active directory and also retrieve their user
> groups.
>
> You must replace the LDAP://yourdomain with the actual domain that you'd
> like to authenticate against.
>
> Please do with this as you will (and use at your own risk):
>
> Imports System.DirectoryServices
> Imports System.Runtime.InteropServices
> Imports System.Globalization
>
> Public Class ADAuthenticate
> Private _path As String
> Private _filterAttribute As String
> Private _UserFirstName As String
> Private _UserLastName As String
> Private _UserPath As String
> Private _AuthenticationErrorString As String
>
> Public Function IsAuthenticated(ByVal UserName As String, ByVal Password
> As String) As Boolean
> ' authenticate the user and get some info about them
> Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
> Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> Dim ds As New DirectorySearcher(entry)
> Dim myFilter As String = "(&(objectClass=user)(samaccountname=" +
> UserName + "))"
>
> ds.Filter = myFilter
> ds.PropertiesToLoad.Add("sn")
> ds.PropertiesToLoad.Add("GivenName")
>
> Try
> Dim sRslt As SearchResult = ds.FindOne
> If sRslt Is Nothing Then
> Return False
> Else
> _filterAttribute = UserName
> Dim propName As String
> Dim value As Object
>
> For Each propName In sRslt.Properties.PropertyNames
> For Each value In sRslt.Properties(propName)
> If propName = "sn" Then
> _UserLastName = value
> End If
>
> If propName = "givenname" Then
> _UserFirstName = value
> End If
>
> If propName = "adspath" Then
> _UserPath = value
> End If
>
> Next value
> Next propName
>
> Return True
> End If
>
> sRslt = Nothing
> ds = Nothing
>
> Catch ex As Exception
> _AuthenticationErrorString = ex.Message & "<br>" & ex.StackTrace
> Return False
> Finally
> entry.Dispose()
> entry = Nothing
> ds.Dispose()
> ds = Nothing
> End Try
>
> End Function
>
> Public ReadOnly Property LdapAuthenticationErrorString() As String
> Get
> Return _AuthenticationErrorString
> End Get
> End Property
>
> Public ReadOnly Property LdapUserFirstName() As String
> Get
> Return _UserFirstName
> End Get
> End Property
>
> Public ReadOnly Property LdapUserLastName() As String
> Get
> Return _UserLastName
> End Get
> End Property
>
> Public Function GetUserGroups(ByVal UserName As String, ByVal Password
> As String) As String
> ' get the groups the user belongs to
> Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
> Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> Dim search = New DirectorySearcher(entry)
>
> search.Filter = "(&(objectClass=user)(cn=" + _filterAttribute + "))"
> search.PropertiesToLoad.Add("memberOf")
>
> Dim groupNames As New System.Text.StringBuilder()
>
> Try
> Dim result As SearchResult = search.FindOne()
> Dim propertyCount As Int32 = result.Properties("memberOf").Count
> Dim dn As String
> Dim equalsIndex As Int32, commaIndex As Int32
> Dim propertyCounter As Int32
>
> For propertyCounter = 0 To propertyCount - 1
> dn = result.Properties("memberOf")(propertyCounter)
> equalsIndex = dn.IndexOf("=", 1)
> commaIndex = dn.IndexOf(",", 1)
> If (-1 = equalsIndex) Then
> groupNames.Append(dn)
> Else
> groupNames.Append(dn.Substring((equalsIndex + 1),
> (commaIndex - equalsIndex) - 1))
> groupNames.Append("|")
> End If
>
> Next propertyCounter
>
> Catch ex As Exception
> Throw New Exception("Error obtaining group names. " +
> ex.Message)
> Finally
> entry.Dispose()
> entry = Nothing
> search = Nothing
> End Try
>
> Return groupNames.ToString()
>
> End Function
> End Class
>
> Good luck
> Jon
>
>Raterus Guest
-
Joe Kaplan \(MVP - ADSI\) #3
Re: VB.NET LDAP Class
Actually, the code in that article is pretty bad and contains a number of
flaws that in my opinion make it not worthy of emulation.
Problems in the IsAuthenticated method include:
- They don't use AuthenticationTypes.Secure, so password is sent in clear
text over the network (!)
- They don't properly call Dispose on the IDisposable objects, so memory
leaks will occur, especially given the bugs in the Finalize method for
DirectoryEntry in .NET 1.0 and 1.1
- They make a bad assumption about the source the failure by catching the
general Exception class instead of looking for the "bad credentials" HRESULT
on the COMException that should be thrown
- They make some bad assumptions that won't necessarily work in a
multi-domain forest about looking up the user's user name
Problems in the GetGroups methods include:
- MemberOf attribute includes non-security groups, does not included nested
group membership and does not include the primary group, so essentially that
isn't the correct list
- Use the CN attribute for making a security decision instead of
sAMAccountName even though CN may not be unique in the directory (only the
current container)
- Parse the DN with a naive check ",", even though DN's can contain ","
escaped with \
- Fail to clean up and catch proper exception types as above
As you can see, I'm pretty grumpy about that sample code. Perhaps someday
I'll post something better or it can be fixed. In the mean time, please
don't use it.
Joe K.
"Raterus" <raterus@spam.org> wrote in message
news:eRYH11adEHA.3212@TK2MSFTNGP12.phx.gbl...
I hope you didn't spend too long converting this.. :-)
[url]http://support.microsoft.com/default.aspx?scid=kb;EN-US;326340[/url]
"Jon Delano" <jd31068@hotmail.com> wrote in message
news:94cOc.209721$Oq2.196851@attbi_s52...C#> Hello
>
> After some effort I was able to come up with this class (converted from aPassword> example on MS' web site).
> Put this in a class in you vb.net web project and you should be able to
> authenticate a user against active directory and also retrieve their user
> groups.
>
> You must replace the LDAP://yourdomain with the actual domain that you'd
> like to authenticate against.
>
> Please do with this as you will (and use at your own risk):
>
> Imports System.DirectoryServices
> Imports System.Runtime.InteropServices
> Imports System.Globalization
>
> Public Class ADAuthenticate
> Private _path As String
> Private _filterAttribute As String
> Private _UserFirstName As String
> Private _UserLastName As String
> Private _UserPath As String
> Private _AuthenticationErrorString As String
>
> Public Function IsAuthenticated(ByVal UserName As String, ByValex.StackTrace> As String) As Boolean
> ' authenticate the user and get some info about them
> Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
> Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> Dim ds As New DirectorySearcher(entry)
> Dim myFilter As String = "(&(objectClass=user)(samaccountname=" +
> UserName + "))"
>
> ds.Filter = myFilter
> ds.PropertiesToLoad.Add("sn")
> ds.PropertiesToLoad.Add("GivenName")
>
> Try
> Dim sRslt As SearchResult = ds.FindOne
> If sRslt Is Nothing Then
> Return False
> Else
> _filterAttribute = UserName
> Dim propName As String
> Dim value As Object
>
> For Each propName In sRslt.Properties.PropertyNames
> For Each value In sRslt.Properties(propName)
> If propName = "sn" Then
> _UserLastName = value
> End If
>
> If propName = "givenname" Then
> _UserFirstName = value
> End If
>
> If propName = "adspath" Then
> _UserPath = value
> End If
>
> Next value
> Next propName
>
> Return True
> End If
>
> sRslt = Nothing
> ds = Nothing
>
> Catch ex As Exception
> _AuthenticationErrorString = ex.Message & "<br>" &"))"> Return False
> Finally
> entry.Dispose()
> entry = Nothing
> ds.Dispose()
> ds = Nothing
> End Try
>
> End Function
>
> Public ReadOnly Property LdapAuthenticationErrorString() As String
> Get
> Return _AuthenticationErrorString
> End Get
> End Property
>
> Public ReadOnly Property LdapUserFirstName() As String
> Get
> Return _UserFirstName
> End Get
> End Property
>
> Public ReadOnly Property LdapUserLastName() As String
> Get
> Return _UserLastName
> End Get
> End Property
>
> Public Function GetUserGroups(ByVal UserName As String, ByVal Password
> As String) As String
> ' get the groups the user belongs to
> Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
> Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> Dim search = New DirectorySearcher(entry)
>
> search.Filter = "(&(objectClass=user)(cn=" + _filterAttribute +result.Properties("memberOf").Count> search.PropertiesToLoad.Add("memberOf")
>
> Dim groupNames As New System.Text.StringBuilder()
>
> Try
> Dim result As SearchResult = search.FindOne()
> Dim propertyCount As Int32 => Dim dn As String
> Dim equalsIndex As Int32, commaIndex As Int32
> Dim propertyCounter As Int32
>
> For propertyCounter = 0 To propertyCount - 1
> dn = result.Properties("memberOf")(propertyCounter)
> equalsIndex = dn.IndexOf("=", 1)
> commaIndex = dn.IndexOf(",", 1)
> If (-1 = equalsIndex) Then
> groupNames.Append(dn)
> Else
> groupNames.Append(dn.Substring((equalsIndex + 1),
> (commaIndex - equalsIndex) - 1))
> groupNames.Append("|")
> End If
>
> Next propertyCounter
>
> Catch ex As Exception
> Throw New Exception("Error obtaining group names. " +
> ex.Message)
> Finally
> entry.Dispose()
> entry = Nothing
> search = Nothing
> End Try
>
> Return groupNames.ToString()
>
> End Function
> End Class
>
> Good luck
> Jon
>
>
Joe Kaplan \(MVP - ADSI\) Guest
-
Jon Delano #4
Re: VB.NET LDAP Class
Well slap someone for just trying to help out some.
I made no comments that it was the best option ... only that it worked for
me in what I was doing (I did use AuthenticationTypes.Secure in my code by
the way and I have added the dispose and set the objects to nothing.)
At the very least it might give someone a starting point if they are lost.
"Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@removethis.accenture.com> wrote
in message news:%23LMMvibdEHA.2384@TK2MSFTNGP09.phx.gbl...HRESULT> Actually, the code in that article is pretty bad and contains a number of
> flaws that in my opinion make it not worthy of emulation.
>
> Problems in the IsAuthenticated method include:
> - They don't use AuthenticationTypes.Secure, so password is sent in clear
> text over the network (!)
> - They don't properly call Dispose on the IDisposable objects, so memory
> leaks will occur, especially given the bugs in the Finalize method for
> DirectoryEntry in .NET 1.0 and 1.1
> - They make a bad assumption about the source the failure by catching the
> general Exception class instead of looking for the "bad credentials"nested> on the COMException that should be thrown
> - They make some bad assumptions that won't necessarily work in a
> multi-domain forest about looking up the user's user name
>
> Problems in the GetGroups methods include:
> - MemberOf attribute includes non-security groups, does not includedthat> group membership and does not include the primary group, so essentiallya> isn't the correct list
> - Use the CN attribute for making a security decision instead of
> sAMAccountName even though CN may not be unique in the directory (only the
> current container)
> - Parse the DN with a naive check ",", even though DN's can contain ","
> escaped with \
> - Fail to clean up and catch proper exception types as above
>
> As you can see, I'm pretty grumpy about that sample code. Perhaps someday
> I'll post something better or it can be fixed. In the mean time, please
> don't use it.
>
> Joe K.
>
>
> "Raterus" <raterus@spam.org> wrote in message
> news:eRYH11adEHA.3212@TK2MSFTNGP12.phx.gbl...
> I hope you didn't spend too long converting this.. :-)
> [url]http://support.microsoft.com/default.aspx?scid=kb;EN-US;326340[/url]
>
> "Jon Delano" <jd31068@hotmail.com> wrote in message
> news:94cOc.209721$Oq2.196851@attbi_s52...> > Hello
> >
> > After some effort I was able to come up with this class (converted fromuser> C#> > example on MS' web site).
> > Put this in a class in you vb.net web project and you should be able to
> > authenticate a user against active directory and also retrieve their+> Password> > groups.
> >
> > You must replace the LDAP://yourdomain with the actual domain that you'd
> > like to authenticate against.
> >
> > Please do with this as you will (and use at your own risk):
> >
> > Imports System.DirectoryServices
> > Imports System.Runtime.InteropServices
> > Imports System.Globalization
> >
> > Public Class ADAuthenticate
> > Private _path As String
> > Private _filterAttribute As String
> > Private _UserFirstName As String
> > Private _UserLastName As String
> > Private _UserPath As String
> > Private _AuthenticationErrorString As String
> >
> > Public Function IsAuthenticated(ByVal UserName As String, ByVal> > As String) As Boolean
> > ' authenticate the user and get some info about them
> > Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
> > Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> > Dim ds As New DirectorySearcher(entry)
> > Dim myFilter As String = "(&(objectClass=user)(samaccountname="Password> ex.StackTrace> > UserName + "))"
> >
> > ds.Filter = myFilter
> > ds.PropertiesToLoad.Add("sn")
> > ds.PropertiesToLoad.Add("GivenName")
> >
> > Try
> > Dim sRslt As SearchResult = ds.FindOne
> > If sRslt Is Nothing Then
> > Return False
> > Else
> > _filterAttribute = UserName
> > Dim propName As String
> > Dim value As Object
> >
> > For Each propName In sRslt.Properties.PropertyNames
> > For Each value In sRslt.Properties(propName)
> > If propName = "sn" Then
> > _UserLastName = value
> > End If
> >
> > If propName = "givenname" Then
> > _UserFirstName = value
> > End If
> >
> > If propName = "adspath" Then
> > _UserPath = value
> > End If
> >
> > Next value
> > Next propName
> >
> > Return True
> > End If
> >
> > sRslt = Nothing
> > ds = Nothing
> >
> > Catch ex As Exception
> > _AuthenticationErrorString = ex.Message & "<br>" &> > Return False
> > Finally
> > entry.Dispose()
> > entry = Nothing
> > ds.Dispose()
> > ds = Nothing
> > End Try
> >
> > End Function
> >
> > Public ReadOnly Property LdapAuthenticationErrorString() As String
> > Get
> > Return _AuthenticationErrorString
> > End Get
> > End Property
> >
> > Public ReadOnly Property LdapUserFirstName() As String
> > Get
> > Return _UserFirstName
> > End Get
> > End Property
> >
> > Public ReadOnly Property LdapUserLastName() As String
> > Get
> > Return _UserLastName
> > End Get
> > End Property
> >
> > Public Function GetUserGroups(ByVal UserName As String, ByVal> "))"> > As String) As String
> > ' get the groups the user belongs to
> > Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
> > Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> > Dim search = New DirectorySearcher(entry)
> >
> > search.Filter = "(&(objectClass=user)(cn=" + _filterAttribute +> result.Properties("memberOf").Count> > search.PropertiesToLoad.Add("memberOf")
> >
> > Dim groupNames As New System.Text.StringBuilder()
> >
> > Try
> > Dim result As SearchResult = search.FindOne()
> > Dim propertyCount As Int32 =>> > Dim dn As String
> > Dim equalsIndex As Int32, commaIndex As Int32
> > Dim propertyCounter As Int32
> >
> > For propertyCounter = 0 To propertyCount - 1
> > dn = result.Properties("memberOf")(propertyCounter)
> > equalsIndex = dn.IndexOf("=", 1)
> > commaIndex = dn.IndexOf(",", 1)
> > If (-1 = equalsIndex) Then
> > groupNames.Append(dn)
> > Else
> > groupNames.Append(dn.Substring((equalsIndex + 1),
> > (commaIndex - equalsIndex) - 1))
> > groupNames.Append("|")
> > End If
> >
> > Next propertyCounter
> >
> > Catch ex As Exception
> > Throw New Exception("Error obtaining group names. " +
> > ex.Message)
> > Finally
> > entry.Dispose()
> > entry = Nothing
> > search = Nothing
> > End Try
> >
> > Return groupNames.ToString()
> >
> > End Function
> > End Class
> >
> > Good luck
> > Jon
> >
> >
>
Jon Delano Guest
-
Joe Kaplan \(MVP - ADSI\) #5
Re: VB.NET LDAP Class
I wasn't criticizing your code Jon, I was criticizing the code in the
article that Raterus pointed to when he suggested that you should have just
used it as an example instead. That is a KBase article and needs to be held
to a higher standard. It is a big pet peeve of mine.
Your code is basically fine by me! Sorry for the confusion :)
Joe K.
"Jon Delano" <jd31068@hotmail.com> wrote in message
news:sgsOc.216053$XM6.171248@attbi_s53...of> Well slap someone for just trying to help out some.
>
> I made no comments that it was the best option ... only that it worked for
> me in what I was doing (I did use AuthenticationTypes.Secure in my code by
> the way and I have added the dispose and set the objects to nothing.)
>
> At the very least it might give someone a starting point if they are lost.
>
>
>
> "Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@removethis.accenture.com> wrote
> in message news:%23LMMvibdEHA.2384@TK2MSFTNGP09.phx.gbl...> > Actually, the code in that article is pretty bad and contains a numberclear> > flaws that in my opinion make it not worthy of emulation.
> >
> > Problems in the IsAuthenticated method include:
> > - They don't use AuthenticationTypes.Secure, so password is sent inmemory> > text over the network (!)
> > - They don't properly call Dispose on the IDisposable objects, sothe> > leaks will occur, especially given the bugs in the Finalize method for
> > DirectoryEntry in .NET 1.0 and 1.1
> > - They make a bad assumption about the source the failure by catchingthe> HRESULT> > general Exception class instead of looking for the "bad credentials"> nested> > on the COMException that should be thrown
> > - They make some bad assumptions that won't necessarily work in a
> > multi-domain forest about looking up the user's user name
> >
> > Problems in the GetGroups methods include:
> > - MemberOf attribute includes non-security groups, does not included> that> > group membership and does not include the primary group, so essentially> > isn't the correct list
> > - Use the CN attribute for making a security decision instead of
> > sAMAccountName even though CN may not be unique in the directory (onlysomeday> > current container)
> > - Parse the DN with a naive check ",", even though DN's can contain ","
> > escaped with \
> > - Fail to clean up and catch proper exception types as above
> >
> > As you can see, I'm pretty grumpy about that sample code. Perhapsfrom> > I'll post something better or it can be fixed. In the mean time, please
> > don't use it.
> >
> > Joe K.
> >
> >
> > "Raterus" <raterus@spam.org> wrote in message
> > news:eRYH11adEHA.3212@TK2MSFTNGP12.phx.gbl...
> > I hope you didn't spend too long converting this.. :-)
> > [url]http://support.microsoft.com/default.aspx?scid=kb;EN-US;326340[/url]
> >
> > "Jon Delano" <jd31068@hotmail.com> wrote in message
> > news:94cOc.209721$Oq2.196851@attbi_s52...> > > Hello
> > >
> > > After some effort I was able to come up with this class (convertedto> a> > C#> > > example on MS' web site).
> > > Put this in a class in you vb.net web project and you should be ableyou'd> user> > > authenticate a user against active directory and also retrieve their> > > groups.
> > >
> > > You must replace the LDAP://yourdomain with the actual domain that"(&(objectClass=user)(samaccountname="> > Password> > > like to authenticate against.
> > >
> > > Please do with this as you will (and use at your own risk):
> > >
> > > Imports System.DirectoryServices
> > > Imports System.Runtime.InteropServices
> > > Imports System.Globalization
> > >
> > > Public Class ADAuthenticate
> > > Private _path As String
> > > Private _filterAttribute As String
> > > Private _UserFirstName As String
> > > Private _UserLastName As String
> > > Private _UserPath As String
> > > Private _AuthenticationErrorString As String
> > >
> > > Public Function IsAuthenticated(ByVal UserName As String, ByVal> > > As String) As Boolean
> > > ' authenticate the user and get some info about them
> > > Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
> > > Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> > > Dim ds As New DirectorySearcher(entry)
> > > Dim myFilter As String =+> +> Password> > ex.StackTrace> > > UserName + "))"
> > >
> > > ds.Filter = myFilter
> > > ds.PropertiesToLoad.Add("sn")
> > > ds.PropertiesToLoad.Add("GivenName")
> > >
> > > Try
> > > Dim sRslt As SearchResult = ds.FindOne
> > > If sRslt Is Nothing Then
> > > Return False
> > > Else
> > > _filterAttribute = UserName
> > > Dim propName As String
> > > Dim value As Object
> > >
> > > For Each propName In sRslt.Properties.PropertyNames
> > > For Each value In sRslt.Properties(propName)
> > > If propName = "sn" Then
> > > _UserLastName = value
> > > End If
> > >
> > > If propName = "givenname" Then
> > > _UserFirstName = value
> > > End If
> > >
> > > If propName = "adspath" Then
> > > _UserPath = value
> > > End If
> > >
> > > Next value
> > > Next propName
> > >
> > > Return True
> > > End If
> > >
> > > sRslt = Nothing
> > > ds = Nothing
> > >
> > > Catch ex As Exception
> > > _AuthenticationErrorString = ex.Message & "<br>" &> > > Return False
> > > Finally
> > > entry.Dispose()
> > > entry = Nothing
> > > ds.Dispose()
> > > ds = Nothing
> > > End Try
> > >
> > > End Function
> > >
> > > Public ReadOnly Property LdapAuthenticationErrorString() As String
> > > Get
> > > Return _AuthenticationErrorString
> > > End Get
> > > End Property
> > >
> > > Public ReadOnly Property LdapUserFirstName() As String
> > > Get
> > > Return _UserFirstName
> > > End Get
> > > End Property
> > >
> > > Public ReadOnly Property LdapUserLastName() As String
> > > Get
> > > Return _UserLastName
> > > End Get
> > > End Property
> > >
> > > Public Function GetUserGroups(ByVal UserName As String, ByVal> > > As String) As String
> > > ' get the groups the user belongs to
> > > Dim entry As New DirectoryEntry("LDAP://yourdomain", UserName,
> > > Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> > > Dim search = New DirectorySearcher(entry)
> > >
> > > search.Filter = "(&(objectClass=user)(cn=" + _filterAttribute>> > "))"> > result.Properties("memberOf").Count> > > search.PropertiesToLoad.Add("memberOf")
> > >
> > > Dim groupNames As New System.Text.StringBuilder()
> > >
> > > Try
> > > Dim result As SearchResult = search.FindOne()
> > > Dim propertyCount As Int32 => >> > > Dim dn As String
> > > Dim equalsIndex As Int32, commaIndex As Int32
> > > Dim propertyCounter As Int32
> > >
> > > For propertyCounter = 0 To propertyCount - 1
> > > dn = result.Properties("memberOf")(propertyCounter)
> > > equalsIndex = dn.IndexOf("=", 1)
> > > commaIndex = dn.IndexOf(",", 1)
> > > If (-1 = equalsIndex) Then
> > > groupNames.Append(dn)
> > > Else
> > > groupNames.Append(dn.Substring((equalsIndex + 1),
> > > (commaIndex - equalsIndex) - 1))
> > > groupNames.Append("|")
> > > End If
> > >
> > > Next propertyCounter
> > >
> > > Catch ex As Exception
> > > Throw New Exception("Error obtaining group names. " +
> > > ex.Message)
> > > Finally
> > > entry.Dispose()
> > > entry = Nothing
> > > search = Nothing
> > > End Try
> > >
> > > Return groupNames.ToString()
> > >
> > > End Function
> > > End Class
> > >
> > > Good luck
> > > Jon
> > >
> > >
> >
>
Joe Kaplan \(MVP - ADSI\) Guest
-
Raterus #6
Re: VB.NET LDAP Class
This isn't the first time Joe has mentioned the faults in this code either, when I was trying to do what you are doing, I kept finding posts by him suggesting better ways, so I listened. Here is how I've been getting my groups after looking through all of his suggestions. It basically revolves around the use of tokenGroups.
I modified this too, for my purposes I needed a delimited string of groupnames. You also have to create the DirectoryEntry based on the user you are interested in, in the class I created I had already done that, so that is why you don't see "dn" declared, just used.
Private Function GetGroups() As String
Dim octetSid As String
Dim binarySid() As Byte
Dim binarySids As PropertyValueCollection
Dim iterator As Integer
Dim groups As StringBuilder = New StringBuilder
Dim gEntry As DirectoryEntry = New DirectoryEntry("LDAP://" & dn)
gEntry.RefreshCache(New String() {"tokenGroups"})
binarySids = gEntry.Properties("tokenGroups")
For iterator = 0 To binarySids.Count - 1
binarySid = CType(binarySids(iterator), Byte())
octetSid = ConvertToOctetString(binarySid)
Dim groupPath As String = String.Format("<SID={0}>", octetSid)
Dim groupEntry As New DirectoryEntry("LDAP://" & groupPath)
If iterator > 0 Then
groups.Append("|")
End If
groups.Append(groupEntry.Properties("sAMAccountNam e").Value.ToString())
Next
Return groups.ToString
End Function
Private Function ConvertToOctetString(ByVal value As Byte()) As String
Dim iterator As Integer
Dim builder As System.Text.StringBuilder
builder = New System.Text.StringBuilder((value.GetUpperBound(0) + 1) * 2)
For iterator = 0 To value.GetUpperBound(0)
builder.Append(value(iterator).ToString("x2"))
Next
Return builder.ToString()
End Function
--Michael
"Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@removethis.accenture.com> wrote in message news:OhFA1nkdEHA.712@TK2MSFTNGP09.phx.gbl...> I wasn't criticizing your code Jon, I was criticizing the code in the
> article that Raterus pointed to when he suggested that you should have just
> used it as an example instead. That is a KBase article and needs to be held
> to a higher standard. It is a big pet peeve of mine.
>
> Your code is basically fine by me! Sorry for the confusion :)
>
> Joe K.Raterus Guest
-
Joe Kaplan \(MVP - ADSI\) #7
Re: VB.NET LDAP Class
Sorry for going off on your post too. Every time I see that article
mentioned, it makes me cringe though, so I tend to over react.
The code below is a much more solid approach. I'd recommend calling Dispose
on your DirectoryEntry objects in a finally block to ensure that you don't
leak memory, but this technique works.
I have a newer technique that uses the DirectorySearcher to do a search for
all of the SIDs at once which is a fair amount faster than binding to each
individual group, but that is just an optimization. It probably only
matters if the user is in many groups.
The downside of all of these approaches is that you should really use the
fully qualified group name (domain\name), but it isn't easy to figure out
the NETBIOS name of the domain given the SID (possible, just not easy). I'm
thinking of trying to use the DsCrackNames API via p/invoke to accomplish
this in my next attempt.
Joe K.
"Raterus" <raterus@spam.org> wrote in message
news:OoIdfKldEHA.3308@TK2MSFTNGP11.phx.gbl...
This isn't the first time Joe has mentioned the faults in this code either,
when I was trying to do what you are doing, I kept finding posts by him
suggesting better ways, so I listened. Here is how I've been getting my
groups after looking through all of his suggestions. It basically revolves
around the use of tokenGroups.
I modified this too, for my purposes I needed a delimited string of
groupnames. You also have to create the DirectoryEntry based on the user
you are interested in, in the class I created I had already done that, so
that is why you don't see "dn" declared, just used.
Private Function GetGroups() As String
Dim octetSid As String
Dim binarySid() As Byte
Dim binarySids As PropertyValueCollection
Dim iterator As Integer
Dim groups As StringBuilder = New StringBuilder
Dim gEntry As DirectoryEntry = New DirectoryEntry("LDAP://" & dn)
gEntry.RefreshCache(New String() {"tokenGroups"})
binarySids = gEntry.Properties("tokenGroups")
For iterator = 0 To binarySids.Count - 1
binarySid = CType(binarySids(iterator), Byte())
octetSid = ConvertToOctetString(binarySid)
Dim groupPath As String = String.Format("<SID={0}>", octetSid)
Dim groupEntry As New DirectoryEntry("LDAP://" & groupPath)
If iterator > 0 Then
groups.Append("|")
End If
groups.Append(groupEntry.Properties("sAMAccountNam e").Value.ToString())
Next
Return groups.ToString
End Function
Private Function ConvertToOctetString(ByVal value As Byte()) As String
Dim iterator As Integer
Dim builder As System.Text.StringBuilder
builder = New System.Text.StringBuilder((value.GetUpperBound(0) + 1)
* 2)
For iterator = 0 To value.GetUpperBound(0)
builder.Append(value(iterator).ToString("x2"))
Next
Return builder.ToString()
End Function
--Michael
"Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@removethis.accenture.com> wrote
in message news:OhFA1nkdEHA.712@TK2MSFTNGP09.phx.gbl...just> I wasn't criticizing your code Jon, I was criticizing the code in the
> article that Raterus pointed to when he suggested that you should haveheld> used it as an example instead. That is a KBase article and needs to be> to a higher standard. It is a big pet peeve of mine.
>
> Your code is basically fine by me! Sorry for the confusion :)
>
> Joe K.
Joe Kaplan \(MVP - ADSI\) Guest
-
Jon Delano #8
Re: VB.NET LDAP Class
No problem ...I just noticed that we have emailed before (I had used ADO to
first query Active Directory) ... and I sent you what I came up with. (Its
the IsAuthenticated part of the class I created later) ... after you pointed
me in the direction of the DirectoryEntry stuff.
LOL .. too funny.
Anyway, thanks and I'm sorry I took it the wrong way ... long weeks and days
....
Take care
Jon
"Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@removethis.accenture.com> wrote
in message news:OhFA1nkdEHA.712@TK2MSFTNGP09.phx.gbl...just> I wasn't criticizing your code Jon, I was criticizing the code in the
> article that Raterus pointed to when he suggested that you should haveheld> used it as an example instead. That is a KBase article and needs to befor> to a higher standard. It is a big pet peeve of mine.
>
> Your code is basically fine by me! Sorry for the confusion :)
>
> Joe K.
>
> "Jon Delano" <jd31068@hotmail.com> wrote in message
> news:sgsOc.216053$XM6.171248@attbi_s53...> > Well slap someone for just trying to help out some.
> >
> > I made no comments that it was the best option ... only that it workedby> > me in what I was doing (I did use AuthenticationTypes.Secure in my codelost.> > the way and I have added the dispose and set the objects to nothing.)
> >
> > At the very least it might give someone a starting point if they arewrote> >
> >
> >
> > "Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@removethis.accenture.com>essentially> of> > in message news:%23LMMvibdEHA.2384@TK2MSFTNGP09.phx.gbl...> > > Actually, the code in that article is pretty bad and contains a number> clear> > > flaws that in my opinion make it not worthy of emulation.
> > >
> > > Problems in the IsAuthenticated method include:
> > > - They don't use AuthenticationTypes.Secure, so password is sent in> memory> > > text over the network (!)
> > > - They don't properly call Dispose on the IDisposable objects, so> the> > > leaks will occur, especially given the bugs in the Finalize method for
> > > DirectoryEntry in .NET 1.0 and 1.1
> > > - They make a bad assumption about the source the failure by catching> > HRESULT> > > general Exception class instead of looking for the "bad credentials"> > nested> > > on the COMException that should be thrown
> > > - They make some bad assumptions that won't necessarily work in a
> > > multi-domain forest about looking up the user's user name
> > >
> > > Problems in the GetGroups methods include:
> > > - MemberOf attribute includes non-security groups, does not included> > > group membership and does not include the primary group, so","> the> > that> > > isn't the correct list
> > > - Use the CN attribute for making a security decision instead of
> > > sAMAccountName even though CN may not be unique in the directory (only> > > current container)
> > > - Parse the DN with a naive check ",", even though DN's can containplease> someday> > > escaped with \
> > > - Fail to clean up and catch proper exception types as above
> > >
> > > As you can see, I'm pretty grumpy about that sample code. Perhaps> > > I'll post something better or it can be fixed. In the mean time,UserName,> from> > > don't use it.
> > >
> > > Joe K.
> > >
> > >
> > > "Raterus" <raterus@spam.org> wrote in message
> > > news:eRYH11adEHA.3212@TK2MSFTNGP12.phx.gbl...
> > > I hope you didn't spend too long converting this.. :-)
> > > [url]http://support.microsoft.com/default.aspx?scid=kb;EN-US;326340[/url]
> > >
> > > "Jon Delano" <jd31068@hotmail.com> wrote in message
> > > news:94cOc.209721$Oq2.196851@attbi_s52...
> > > > Hello
> > > >
> > > > After some effort I was able to come up with this class (converted> to> > a> > > C#
> > > > example on MS' web site).
> > > > Put this in a class in you vb.net web project and you should be able> you'd> > user> > > > authenticate a user against active directory and also retrieve their> > > > groups.
> > > >
> > > > You must replace the LDAP://yourdomain with the actual domain that> > > > like to authenticate against.
> > > >
> > > > Please do with this as you will (and use at your own risk):
> > > >
> > > > Imports System.DirectoryServices
> > > > Imports System.Runtime.InteropServices
> > > > Imports System.Globalization
> > > >
> > > > Public Class ADAuthenticate
> > > > Private _path As String
> > > > Private _filterAttribute As String
> > > > Private _UserFirstName As String
> > > > Private _UserLastName As String
> > > > Private _UserPath As String
> > > > Private _AuthenticationErrorString As String
> > > >
> > > > Public Function IsAuthenticated(ByVal UserName As String, ByVal
> > > Password
> > > > As String) As Boolean
> > > > ' authenticate the user and get some info about them
> > > > Dim entry As New DirectoryEntry("LDAP://yourdomain",String> "(&(objectClass=user)(samaccountname="> > > > Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> > > > Dim ds As New DirectorySearcher(entry)
> > > > Dim myFilter As String => > +> > > > UserName + "))"
> > > >
> > > > ds.Filter = myFilter
> > > > ds.PropertiesToLoad.Add("sn")
> > > > ds.PropertiesToLoad.Add("GivenName")
> > > >
> > > > Try
> > > > Dim sRslt As SearchResult = ds.FindOne
> > > > If sRslt Is Nothing Then
> > > > Return False
> > > > Else
> > > > _filterAttribute = UserName
> > > > Dim propName As String
> > > > Dim value As Object
> > > >
> > > > For Each propName In sRslt.Properties.PropertyNames
> > > > For Each value In sRslt.Properties(propName)
> > > > If propName = "sn" Then
> > > > _UserLastName = value
> > > > End If
> > > >
> > > > If propName = "givenname" Then
> > > > _UserFirstName = value
> > > > End If
> > > >
> > > > If propName = "adspath" Then
> > > > _UserPath = value
> > > > End If
> > > >
> > > > Next value
> > > > Next propName
> > > >
> > > > Return True
> > > > End If
> > > >
> > > > sRslt = Nothing
> > > > ds = Nothing
> > > >
> > > > Catch ex As Exception
> > > > _AuthenticationErrorString = ex.Message & "<br>" &
> > > ex.StackTrace
> > > > Return False
> > > > Finally
> > > > entry.Dispose()
> > > > entry = Nothing
> > > > ds.Dispose()
> > > > ds = Nothing
> > > > End Try
> > > >
> > > > End Function
> > > >
> > > > Public ReadOnly Property LdapAuthenticationErrorString() AsUserName,> > Password> > > > Get
> > > > Return _AuthenticationErrorString
> > > > End Get
> > > > End Property
> > > >
> > > > Public ReadOnly Property LdapUserFirstName() As String
> > > > Get
> > > > Return _UserFirstName
> > > > End Get
> > > > End Property
> > > >
> > > > Public ReadOnly Property LdapUserLastName() As String
> > > > Get
> > > > Return _UserLastName
> > > > End Get
> > > > End Property
> > > >
> > > > Public Function GetUserGroups(ByVal UserName As String, ByVal> > > > As String) As String
> > > > ' get the groups the user belongs to
> > > > Dim entry As New DirectoryEntry("LDAP://yourdomain",_filterAttribute> > > > Password, System.DirectoryServices.AuthenticationTypes.Secur e)
> > > > Dim search = New DirectorySearcher(entry)
> > > >
> > > > search.Filter = "(&(objectClass=user)(cn=" +1),> +> > > "))"
> > > > search.PropertiesToLoad.Add("memberOf")
> > > >
> > > > Dim groupNames As New System.Text.StringBuilder()
> > > >
> > > > Try
> > > > Dim result As SearchResult = search.FindOne()
> > > > Dim propertyCount As Int32 =
> > > result.Properties("memberOf").Count
> > > > Dim dn As String
> > > > Dim equalsIndex As Int32, commaIndex As Int32
> > > > Dim propertyCounter As Int32
> > > >
> > > > For propertyCounter = 0 To propertyCount - 1
> > > > dn = result.Properties("memberOf")(propertyCounter)
> > > > equalsIndex = dn.IndexOf("=", 1)
> > > > commaIndex = dn.IndexOf(",", 1)
> > > > If (-1 = equalsIndex) Then
> > > > groupNames.Append(dn)
> > > > Else
> > > > groupNames.Append(dn.Substring((equalsIndex +>> >> > > > (commaIndex - equalsIndex) - 1))
> > > > groupNames.Append("|")
> > > > End If
> > > >
> > > > Next propertyCounter
> > > >
> > > > Catch ex As Exception
> > > > Throw New Exception("Error obtaining group names. " +
> > > > ex.Message)
> > > > Finally
> > > > entry.Dispose()
> > > > entry = Nothing
> > > > search = Nothing
> > > > End Try
> > > >
> > > > Return groupNames.ToString()
> > > >
> > > > End Function
> > > > End Class
> > > >
> > > > Good luck
> > > > Jon
> > > >
> > > >
> > >
> > >
> >
>
Jon Delano Guest



Reply With Quote

