近期開發一個採用 File Mapping 進行進程間通訊 (IPC) 的方案,旨在實現 Web Service 與自訂服務之間的安全隔離與狀態管理。測試發現,在一般 Windows 進程間通訊正常,但將客戶端移植至 ASP.NET 後,開啟 File Mapping 失敗,顯然是權限問題。
以下提供可直接使用的 C# 程式碼,採用 P/Invoke 呼叫 Windows API 建立 NULL DACL 的 SecurityAttributes 類別:
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct SECURITY_DESCRIPTOR
{
public byte revision;
public byte size;
public short control;
public IntPtr owner;
public IntPtr group;
public IntPtr sacl;
public IntPtr dacl;
}
[StructLayout(LayoutKind.Sequential)]
public class SecurityAttributes : IDisposable
{
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool SetSecurityDescriptorDacl(IntPtr sd, bool daclPresent, IntPtr dacl, bool daclDefaulted);
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool InitializeSecurityDescriptor(IntPtr pSecurityDescriptor, uint dwRevision);
private int nLength;
private IntPtr lpSecurityDescriptor;
private int bInheritHandle;
public SecurityAttributes()
{
nLength = Marshal.SizeOf(typeof(SecurityAttributes));
bInheritHandle = 1;
SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR();
lpSecurityDescriptor = Marshal.AllocCoTaskMem(Marshal.SizeOf(sd));
Marshal.StructureToPtr(sd, lpSecurityDescriptor, false);
InitializeSecurityDescriptor(lpSecurityDescriptor, 1);
SetSecurityDescriptorDacl(lpSecurityDescriptor, true, IntPtr.Zero, false);
}
public void Dispose()
{
lock (this)
{
if (lpSecurityDescriptor != IntPtr.Zero)
{
Marshal.FreeHGlobal(lpSecurityDescriptor);
lpSecurityDescriptor = IntPtr.Zero;
}
}
}
~SecurityAttributes()
{
Dispose();
}
}
建立 File Mapping 時傳入此 SecurityAttributes 實例即可:
using (var sa = new SecurityAttributes())
{
IntPtr handle = CreateFileMapping(
IntPtr.Zero, sa, PageReadWrite, 0, size, name);
// 後續操作...
}
方案三(精確授權特定進程)的完整實作將於後續文章補充。若專案對安全性要求極高,建議投入精力實作方案三。