You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Windows进程间数据传输及同一用户身份验证?

Windows下同一用户进程间安全通信方案

针对同一Windows机器上、需操作系统验证双方为*同一用户(相同SID)*的进程间安全通信需求,以下是几种替代Linux/Unix套接字+SO_PEERCRED的方案:

一、命名管道(Named Pipes)—— 原生首选IPC方案

命名管道是Windows原生IPC机制,自带安全控制能力,可直接实现同一用户进程的身份验证:

  1. 创建管道时限制访问权限
    创建命名管道时,通过SECURITY_ATTRIBUTES设置仅允许当前用户访问的安全描述符,从源头阻止非授权进程连接。示例代码片段:

    SECURITY_ATTRIBUTES sa = {0};
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = FALSE;
    // 生成仅当前用户可完全访问的安全描述符(需替换为实际当前用户SID)
    ConvertStringSecurityDescriptorToSecurityDescriptor(
        L"D:P(A;;GA;;;S-1-5-21-XXXXXXXXX-XXXXXXXXX-XXXXXXXXX-XXXXXX)", 
        SDDL_REVISION_1, 
        &sa.lpSecurityDescriptor, 
        NULL);
    HANDLE hPipe = CreateNamedPipe(
        L"\\\\.\\pipe\\MySecurePipe",
        PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
        PIPE_UNLIMITED_INSTANCES,
        4096,
        4096,
        0,
        &sa);
    
  2. 接收方验证客户端身份
    客户端连接后,通过系统API获取其进程ID,再提取进程令牌中的SID与自身SID对比:

    DWORD clientPid;
    GetNamedPipeClientProcessId(hPipe, &clientPid);
    // 打开客户端进程并获取令牌
    HANDLE hClientProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, clientPid);
    HANDLE hClientToken;
    OpenProcessToken(hClientProcess, TOKEN_QUERY, &hClientToken);
    // 提取客户端SID
    DWORD sidSize = 0;
    GetTokenInformation(hClientToken, TokenUser, NULL, 0, &sidSize);
    PTOKEN_USER pTokenUser = (PTOKEN_USER)LocalAlloc(LPTR, sidSize);
    GetTokenInformation(hClientToken, TokenUser, pTokenUser, sidSize, &sidSize);
    // 获取自身SID并对比
    HANDLE hSelfToken;
    OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hSelfToken);
    // 省略自身SID提取逻辑,用EqualSid完成对比
    BOOL isSameUser = EqualSid(pTokenUser->User.Sid, selfSid);
    

二、Unix域套接字(Windows 10 1709+)—— 类Linux SO_PEERCRED方案

Windows 10 1709及以上版本支持AF_UNIX套接字,可通过GetUnixSocketPeerCredentials直接获取对等方凭据,实现与Linux SO_PEERCRED一致的验证逻辑:

  1. 创建Unix套接字
    服务端创建AF_UNIX类型套接字,绑定到本地管道路径(Windows下Unix套接字路径需以\\.\pipe\开头):

    SOCKET sock = socket(AF_UNIX, SOCK_STREAM, 0);
    struct sockaddr_un addr = {0};
    addr.sun_family = AF_UNIX;
    wcscpy_s(addr.sun_path, L"\\\\.\\pipe\\MyUnixSocket");
    bind(sock, (struct sockaddr*)&addr, sizeof(addr));
    listen(sock, 5);
    
  2. 验证对等方身份
    接受连接后,调用getsockopt配合SO_PEERCRED选项获取客户端PID,后续流程同命名管道的SID对比:

    SOCKET clientSock = accept(sock, NULL, NULL);
    UNIX_SOCKET_PEER_CREDENTIALS creds;
    DWORD credSize = sizeof(creds);
    getsockopt(clientSock, SOL_SOCKET, SO_PEERCRED, (char*)&creds, &credSize);
    DWORD clientPid = creds.ProcessId;
    // 通过PID提取客户端SID并与自身对比(逻辑同命名管道)
    

三、本地TCP套接字+SSPI身份验证

使用127.0.0.1的TCP套接字,结合Windows SSPI(安全支持提供程序接口)完成NTLM/Kerberos身份验证,由系统自动确认双方为同一用户:

  • 客户端调用InitializeSecurityContext发起验证请求,服务端调用AcceptSecurityContext响应;
  • 验证通过后,系统已确认双方属于同一用户,无需手动处理SID对比。

四、非套接字方案:文件映射+令牌验证

若无需套接字风格的流式通信,可采用文件映射实现IPC,结合令牌验证:

  1. 创建文件映射时,设置仅当前用户可访问的安全描述符,确保只有同一用户的进程能打开映射;
  2. 通信过程中,接收方可通过共享同步对象(如事件)获取发送方进程ID,再通过OpenProcessToken提取SID完成对比。

内容的提问来源于stack exchange,提问作者Cort Ammon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 10:17:50