我试图做的事情在原则上似乎很简单。有一个目录包含我需要提供给我的用户的文档,但是运行 IIS 的帐户没有访问权限。因此,我尝试做的是使用模拟在 .ashx 中打开文档,并使用具有访问权限的帐户将文档写入响应流。不幸的是,除非我将网站托管在我以管理员身份运行的 Visual Studio 实例中,否则下面的代码片段会因using (Stream fileStream = new FileStream(@"c:\test3.pdf", FileMode.Open))
System.UnauthorizedAccessException而失败。这似乎没有意义,因为模仿似乎已经生效WindowsIdentity.GetCurrent().Name
返回我的测试帐户的名称,并且测试帐户确实有权打开文档。好像我在这里遗漏了一些非常简单的东西有人知道它是什么吗?我感谢任何帮助!!!!
<%@ WebHandler Language="C#" Class="PDFHandler" %>
using System;
using System.Web;
using System.IO;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Threading;
public class PDFHandler : IHttpHandler {
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
String lpszUsername,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
public void ProcessRequest (HttpContext context) {
context.Response.Clear();
context.Response.ClearContent();
context.Response.ClearHeaders();
context.Response.ContentType = "application/pdf";
byte[] result = null;
IntPtr admin_token = default(IntPtr);
WindowsIdentity wid_current = WindowsIdentity.GetCurrent();
WindowsIdentity wid_admin = null;
WindowsImpersonationContext wic = null;
RevertToSelf();
if (LogonUser("test account", "Odysseus", "test", 2, 0, ref admin_token) == true)
{
wid_admin = new WindowsIdentity(admin_token);
wic = wid_admin.Impersonate();
using (Stream fileStream = new FileStream(@"c:\test3.pdf", FileMode.Open))
{
result = ReadFully(fileStream);
fileStream.Close();
}
}
else
{
//login failed
}
context.Response.BinaryWrite(result);
context.Response.Flush();
}
public static byte[] ReadFully(Stream input)
{
byte[] returnValue;
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
returnValue = ms.ToArray();
}
return returnValue;
}
public bool IsReusable {
get {
return false;
}
}
}