문제

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.

도움이 되었습니까?

해결책

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top