IPC进行命名管道通信时,服务端是一个本地的service,客户端则是网页插件。
由于网页插件的权限是受浏览器启动权限限制的,很多操作无法进行。
目前遇到的一个问题是,在客户端准备与服务端通过命名管道建立连接的时候,发现在win7中,关闭UAC则通讯没有问题,
但是在开启UAC后,客户端与服务端建立连接就会失败,原因在于Windows通过UAC限制了插件对磁盘的写操作,在研究了一番后发现,
客户端因为权限不够,所以无法建立对文件进行写操作,而读写管道是被看作文件操作的,所以导致权限不足而失败。
所以总结一下:
对于以上问题,说到底,就是因为权限的原因,所以解决就要从权限入手,两种方案,一种是提升客户端运行权限,另外一种就是降低服务端访问权限
对于第一种:
一般只对exe有效,而对浏览器使用的插件dll或者ocx无效
1.可以采用的方式是在
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
注册表中添加上该exe的路径,值为RUNASADMIN
就可以使exe每次都以管理员权限启动
2.可以在VS中编译的时候 修改链接器中的清单UAC来提升运行权限,具体操作为:
项目-》属性-》链接器-》清单文件-》
生成清单文件:是
启用用户账户控制(UAC):是
UAC执行级别:requireAdministrator
对于第二种:
降低服务端访问权限,主要针对上述需求,因为使用命名管道是采用CreateFile来创建的管道,而CreateFile的最后一个参数
handle = CreateNamedPipe(
(const wchar_t *)fullServerName.utf16(), // pipe name
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_BYTE | // byte type pipe
PIPE_READMODE_BYTE | // byte-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZE, // output buffer size
BUFSIZE, // input buffer size
3000, // client time-out
sa);
sa就是描述创建的权限,针对sa的设置,参考如下代码
SECURITY_ATTRIBUTES sa;//声明一个SA
SECURITY_DESCRIPTOR sd; //声明一个SD
BYTE aclBuffer[1024], sidBuffer[100];
PACL pacl = (PACL)&aclBuffer;//声明一个ACL,长度是1024
PSID psid = (PSID) &sidBuffer;//声明一个SID,长度是100
SID_NAME_USE snu;
DWORD sidBufferSize = 100, domainBufferSize = 80;
TCHAR domainBuffer[80];
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
InitializeAcl(pacl, 1024, ACL_REVISION);
LookupAccountName(0, L"everyone", psid, &sidBufferSize, domainBuffer, &domainBufferSize, &snu);
AddAccessAllowedAce(pacl, ACL_REVISION, GENERIC_ALL, psid);
SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;//把SD设置到SA中
sa.bInheritHandle = FALSE;
红色部分就表示,声明该管道为everyone都可以访问的权限
就这样,降低了service中命名管道的访问权限,即时客户端不是以管理员启动,也可以进行管道的读写了。
同样,这样的思路也可以用于别的地方
下图是关于Windows 7高低权限进程通信的权限对结果的影响,可以推断出,要想双方进行通讯,发送发的权限必须要大于等于接收放的权限才行