asp.netvb.netconnection-stringdatabase-permissionsintegrated-security

Error: Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'. in VB.Net


Although I found many posts with this same error, I couldn't find if my error is fixable or not.

There is a database which I have read permission with my window login on the network. I just use SSMS to access the table but that isn't really have the best interface in the world so I wrote a small website that can connect to the table and filter the data I want and display them nicely.

I use Integrated Security = SSPI (also tried TRUE) and it all works fine until this point. I run the website using VS2010. But running a website using VS2010 isn't really ideal thing to do so I put my website on IIS 7 on my machine (i.e. Localhost:xxx). And this's when I got the above error.

All those issues can be fixed if I can just get a user in the database with only a read permission to the table I want to read but that isn't simply possible in my case. There is nothing i can change with the database.

So is there any work around to host the website on local IIS with a connection string that uses integrated security and connects to a remote database with window login credential?

Thanks.


Solution

  • If you know User ID/Password of Windows user, used in Integrated security login, you can try following approach.

    First declare calls to Windows API functions:

    Private Enum LogonSessionType As Integer
      Interactive = 2
      Network
      Batch
      Service
      NetworkCleartext = 8
      NewCredentials
    End Enum
    
    Private Enum LogonProvider As Integer
      WinDefault = 0
      WinNT35
      WinNT40
      WinNT50
    End Enum
    
    <DllImport("advapi32.dll", SetLastError:=True)> _
    Private Shared Function LogonUser(ByVal userID As String, _
                                      ByVal domain As String, _
                                      ByVal password As String, _
                                      ByVal logonType As LogonSessionType, _
                                      ByVal LogonProv As LogonProvider, _
                                      ByRef token As IntPtr) As Boolean
    End Function
    
    <DllImport("kernel32.dll", SetLastError:=True)> _
    Private Shared Function CloseHandle(ByVal handle As IntPtr) As Boolean
    
    End Function
    

    Then declare 2 helper functions

    Sub BeginImpersonate(ByVal i_sUserID As String, ByVal i_sPassword As String, ByRef o_impersonatedUser As WindowsImpersonationContext, ByRef o_token As IntPtr)
    
        o_token = IntPtr.Zero
        o_impersonatedUser = Nothing
    
        Dim bLoginSuccessful As Boolean = LogonUser(i_sUserID, Nothing, i_sPassword, LogonSessionType.Interactive, LogonProvider.WinDefault, o_token)
    
        If bLoginSuccessful Then
             Dim id As New WindowsIdentity(o_token)
             o_impersonatedUser = id.Impersonate()
        Else
             Throw New Exception ("Logon failed: Error " & Marshal.GetLastWin32Error.ToString)
        End If
    
    End Sub
    
    
    Sub EndImpersonate(ByVal i_impersonatedUser As WindowsImpersonationContext, ByVal i_token As IntPtr)
        If i_impersonatedUser IsNot Nothing Then i_impersonatedUser.Undo()
        If i_token <> IntPtr.Zero Then CloseHandle(i_token)
    End Sub
    

    With this preparation made you can make calls like this:

    Dim impersonatedUser As WindowsImpersonationContext = Nothing
    Dim token As IntPtr = IntPtr.Zero
    
    BeginImpersonate(i_sUserID, i_sPassword, impersonatedUser, token)
    
    'Do your DB stufff here, open connection etc.
    
    EndImpersonate(impersonatedUser, token)
    

    This code is kind of raw, but it works. You will need to add appropriate error handling etc. to make it a production code. Pass user ID in format "user@domain" in "i_sUserID" parameter and user's password in "i_sPassword" parameter.