我正在处理一些asp.net页面,这些页面驻留的是一个巨大的Intranet应用程序,Intranet应用程序池以身份NetworkService
(不要问)和&使用匿名身份验证作为IUSR - IIS7。
我们说Intranet Home Dir是D:\Intranet\
- 有问题的asp.net页面位于D:\Intranet\TimeSheets\V2\
我的测试脚本是D:\Intranet\TimeSheets\V2\Post.aspx
并在这些行上做了一些事情(发布HTML [作为基础64字符串]) - 转换为HTML然后尝试写入网络共享:
Dim TimeSheetInBase64 As String = Request.Form("HtmlToSave")
Dim HtmlToSave As String = ""
Dim SavePath As String = "\\DifferentFileServer\Public\Random Department\Posted Invoices\"
'#### Convert the HTML from base64 back into HTML
Try
Dim decodedBytes As Byte()
decodedBytes = Convert.FromBase64String(TimeSheetInBase64)
HtmlToSave = Encoding.Default.GetString(decodedBytes)
Catch e As Exception
echo("Error decoding HTML: " & e.Message)
Exit Select
End Try
Try
Dim objWriter As New System.IO.StreamWriter(SavePath & "text.htm", False)
objWriter.WriteLine(HtmlToSave)
objWriter.Close()
echo("OK")
Catch ex As Exception
Dim wi As WindowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent()
Dim user As String = wi.Name
echo("Error Saving Invoice To Disk (" & wi.Name & "): " & ex.Message)
End Try
尝试将文件写入远程共享时,objWriter会抛出错误:
Error Saving Invoice To Disk (NT AUTHORITY\NETWORK SERVICE): Access to the path '\\DifferentFileServer\Public\Random Department\Posted Invoices\text.htm' is denied.
显然这是因为有问题的页面正在应用程序池的范围内运行。
因此,我尝试更改V2文件夹上的匿名特定用户,以使用对相关共享具有写入权限的AD帐户 - 但是,即使在保存配置更改后,重新启动IIS页面仍会获得访问被拒绝错误在尝试编写文件时(WindowsIdentity.GetCurrent()仍然返回NT AUTHORITY \ NETWORK SERVICE(这是应用程序池的标识,而不是我为匿名访问设置的帐户)。
只是为了确认这是覆盖匿名帐户的问题我设置应用程序池作为我试图在匿名特定用户上使用的AD帐户运行 - 这工作正常并且文件成功写入远程分享 - 所以凭据是好的,只是IIS没有正确使用它们。
我的问题是,是否有可能为匿名用户运行一些具有不同Windows凭据的子文件夹?如果是这样,除了更改匿名帐户之外我还需要做什么,因为这似乎没有效果?
我的第二个问题是:不是依靠IIS来提升权限,有没有办法在asp.net页面内执行此操作,即使用与页面运行的不同凭据编写文件? 我已经考虑将这个子文件夹移动到它自己的应用程序池中 - 但这看起来有点乱,我想尽可能避免这样做。
(抱歉文字墙)
答案 0 :(得分:1)
好吧,在用IIS敲打我的头后,我放弃并走了代码路线,特别是advapi32.dll
,它是LogonUserA()
,DuplicateToken()
& RevertToSelf()
,更重要的是WindowsImpersonationContext对象:
http://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext.aspx
首先,声明函数以在&上切换模拟。关:
Private Function impersonateValidUser(ByVal userName As String, _
ByVal domain As String, ByVal password As String) As Boolean
Dim tempWindowsIdentity As WindowsIdentity
Dim token As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = False
If RevertToSelf() Then
If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
If Not impersonationContext Is Nothing Then
impersonateValidUser = True
End If
End If
End If
End If
If Not tokenDuplicate.Equals(IntPtr.Zero) Then
CloseHandle(tokenDuplicate)
End If
If Not token.Equals(IntPtr.Zero) Then
CloseHandle(token)
End If
End Function
Private Sub undoImpersonation()
impersonationContext.Undo()
End Sub
使用非常简单:
If impersonateValidUser("username", "domain", "password") Then
'#### Write the file then 'close' the Impersonation
undoImpersonation()
End If
以下命名空间,如果需要:
System.Web
System.Web.Security
System.Security.Principal
System.Runtime.InteropServices
灵感(羞耻我花了这么长时间才发现这一点):