3

我试图做的事情在原则上似乎很简单。有一个目录包含我需要提供给我的用户的文档,但是运行 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;
        }
    }

}
4

1 回答 1

0

您可以将此页面移动到新文件夹并添加 web.config 文件。然后使用身份标签启用模拟。阅读有关如何将用户名和密码加密到注册表的注释。

阅读本文的“替代方案”部分

于 2012-11-18T23:20:29.377 回答