DirectoryEntry.NativeObject slow with ASP.Net, but fast in exe

Discussion in 'ASP .Net Security' started by Vadim P, Jan 20, 2006.

  1. Vadim P

    Vadim P Guest

    I am authenticating against an AD using DirectoryEntry and binding by getting
    NativeObject. Just two lines, create DirectoryEntry and call NativeObject.
    Functionally everything works. However, it takes over 13 sec to return
    NativeObject when invoked ASP.Net page. The same exact code in a test exe
    returns in less that one second. The LDAP are inside a utility class that
    lives in library, so the only difference is the how they are being called.

    I traced through the web page and the business object down to the statement
    level and confirmed that it is in fact entry.NativeObject consumes all of
    that time. I added ASPNET and IUSR_xxxxx accounts to the Administrators
    group. I tried every reasonable AuthenticationTypes value.

    If the user authenticates, logs out and authenticates again, the login is
    very quick. I assume this is due to caching.

    Any ideas on how I can improve performance? What should I try next?

    Thank you,
    -Vadim
     
    Vadim P, Jan 20, 2006
    #1
    1. Advertisements

  2. Can I see the code?

    Generally for this type of thing, you should use AuthenticationTypes.Secure.
    The path should either specify no server name or the DNS name of the server
    (not IP address or NETBIOS). Username should generally be in the form
    domain\user or .

    Note that the ADSI approach to authentication doesn't really scale well.
    ADSI will open a new socket for each new user who connects, so you can
    easily run out of TCP wildcard ports under load. To do auth with LDAP under
    high volume, you really need to use a lower level API where you can manage
    the connections yourself such as System.DirectoryServices.Protocols. You'll
    get the best perf if you can use fast concurrent binding, but that requires
    2003 AD or ADAM, 2003 clients and should be combined with SSL since it uses
    plain text credentials.

    If you want a different approach, calling LogonUser or using an SSPI wrapper
    like NegotiateStream is a better idea.

    Joe K.
     
    Joe Kaplan \(MVP - ADSI\), Jan 20, 2006
    #2
    1. Advertisements

  3. Vadim P

    Vadim P Guest

    Joe,

    Thanks for your reply. That's a lot of good info. At this point we are
    testing with just one user and have not yet encountered these issues.

    I am still eager to hear some ideas on why invoking it in exe vs. ASP.Net
    form should matter. The same code executed in an exe runs in less that one
    second. When called in handler for a button click, it taked 13. In both
    cases it athenticates, the only difference is speed of entry.NativeObject
    call.

    The code is (with a few deletions):
    Public Function Authenticate(ByVal domain As String, ByVal username As
    String, ByVal pwd As String) As Boolean

    Dim domainAndUsername As String = domain + "\" + username
    Dim entry As DirectoryEntry = New DirectoryEntry(_path,
    domainAndUsername, pwd, _
    AuthenticationTypes.FastBind)

    Try
    Dim obj As Object = entry.NativeObject
    '...
    Catch ex As System.Runtime.InteropServices.COMException
    '...
    Return False
    End Try

    Return True

    End Function

    _path is set in a prior call. Format is "LDAP://server.domain.com:636"


    Thanks again for your help,
    -Vadim
     
    Vadim P, Jan 20, 2006
    #3
  4. Ah, you are using SSL. In this case, you might want to do
    AuthenticationTypes.FastBind Or AuthenticationTypes.SecureSocketsLayer and
    leave the :636 off of the path. LDAP will pick the port automatically if
    you request SSL. AD always uses 636 for SSL/LDAP.

    One thing that might be going on here is that the web server may be trying
    to authenticate with a client certificate. This tends to slow down the
    initial handshake. If you bump up the Schannel logging level, you'll see
    lots of info about this in the System event log.

    http://support.microsoft.com/?id=260729

    If you are ok with not using SSL, you might just try using AD secure
    authentication (which uses the Negotiate protocol).

    Change your path to:
    LDAP://server.domain.com/rootDSE

    and change your flags to:
    AuthenticationTypes.Secure Or AuthenticationTypes.FastBind

    You won't use SSL here, but your credentials will be validated with
    Kerberos, so no clear text password is sent on the network.

    If you must use SSL, you might want to try to make sure that the process
    account doesn't have a client certificate available that the server trusts.
    This will make the SSL go faster (assuming that was the problem).

    Finally, you might want to sniff the network traffic and see what all is
    going on (easier to do with SSL turned off). It is possible that you may
    have a schema caching issue that is causing ADSI to download the LDAP schema
    from AD. This should not happen repeatedly though.

    HTH,

    Joe K.
     
    Joe Kaplan \(MVP - ADSI\), Jan 21, 2006
    #4
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.