提升IIS工作线程身份以访问内存映射文件

时间:2015-08-26 21:16:00

标签: iis windows-server-2012 iis-8.5

我需要从我的Web API中的一个路由访问内存映射文件。使用正常的IIS工作器设置我没有运气,我的服务总是返回"文件未找到"。我试着添加前缀" Global /"但仍然没有运气。

在网上阅读了好几个小时后,我了解到我需要更改IIS工作者的身份。因此,仅出于测试目的,我将工作者身份更改为管理员帐户。我在这里上传了一张照片:

http://imgur.com/MrA3byz

但仍然没有运气。有没有人知道如何正确配置IIS?

以下是使用c#:

访问内存映射文件的方法
{{1}}

我仔细检查了内存映射文件的名称,这是正确的。以管理员身份运行的命令行工具按预期工作。

我在Windows Server 2012上使用IIS 8.5。

1 个答案:

答案 0 :(得分:0)

这适用于Windows Server 2012和IIS 8.5。

了解IIS工作程序在与正常应用程序不同的终端服务器会话中运行非常重要。很像Windows服务。

因此,当应用程序公开内存映射文件时,它需要通过添加到名称的“Global \”前缀来创建它。但它还需要添加安全描述符或标识。在c#中,它看起来像这样:

string MMF_Name = @"Global\MyMemoryMappedFileName";

var security = new MemoryMappedFileSecurity();
security.AddAccessRule(new System.Security.AccessControl.AccessRule<MemoryMappedFileRights>(new SecurityIdentifier(WellKnownSidType.WorldSid, null)
    , MemoryMappedFileRights.FullControl
    , AccessControlType.Allow)
    );


var mmf = MemoryMappedFile.CreateOrOpen(MMF_Name
    , 1024 * 1024
    , MemoryMappedFileAccess.ReadWrite
    , MemoryMappedFileOptions.None
    , security
    , System.IO.HandleInheritability.Inheritable);

在C ++中它看起来像这样:

TCHAR szName[] = TEXT("Global\MyMemoryMappedFileName");

HANDLE hMapFile;
LPCTSTR pBuf;

SECURITY_DESCRIPTOR sd;

if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
  printf("InitializeSecurityDescriptor failed %d\n", GetLastError());

if (!SetSecurityDescriptorDacl(&sd, true, 0, false))
  printf("SetSecurityDescriptorDacl failed %d\n", GetLastError());

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = false;



hMapFile = CreateFileMapping(
  INVALID_HANDLE_VALUE,    // use paging file
  &sa,                    // default security
  PAGE_READWRITE,          // read/write access
  0,                       // maximum object size (high-order DWORD)
  BUF_SIZE,                // maximum object size (low-order DWORD)
  szName);                 // name of mapping object

if (hMapFile == NULL)
{
  _tprintf(TEXT("Could not create file mapping object (%d).\n"),
       GetLastError());
  return 1;
}

创建此类对象的应用程序需要以管理员权限开始。

现在,当像IIS工作者这样的客户端尝试访问该文件时,需要确保使用正确的名称,即使用“Global”前缀。在C#中它看起来像:

string MMF_Name = @"Global\MyMemoryMappedFileName";

var MMF = MemoryMappedFile.OpenExisting(MMF_Name
    , MemoryMappedFileRights.ReadWrite
    , HandleInheritability.Inheritable);

在C ++中:

TCHAR szName[] = TEXT("Global\\MyMemoryMappedFileName");

HANDLE hMapFile;
LPCTSTR pBuf;

hMapFile = OpenFileMapping(
  FILE_MAP_ALL_ACCESS,   // read/write access
  TRUE,                 // !!!!! do inherit the name
  szName);               // name of mapping object

if (hMapFile == NULL)
{
  _tprintf(TEXT("Could not open file mapping object (%d).\n"),
       GetLastError());
  return 1;
}

完成所有这些后。 IIS工作者应该能够通过内存映射文件访问应用程序。无需更改工人的身份。实际上,我在默认设置下运行它。