如何从RPC_BINDING_HANDLE无副作用获取客户端用户名
已知
RPC_BINDING_HANDLE时无副作用获取客户端用户名的方法 你担心的RpcImpersonateClient+RpcRevertToSelfEx方案实际开销非常低,本质是线程令牌的上下文切换,没有额外跨进程、跨网络通信,只要用结构化异常保证恢复逻辑一定执行,不会出现状态污染问题,但确实存在完全不修改线程全局状态、更轻量的实现方式,不需要走模拟流程:
- 直接调用
RpcServerInqCallAttributes接口做纯查询,全程不改动任何线程、进程级状态:- 实例化
RPC_CALL_ATTRIBUTES_V2_W结构,将结构的Version字段设为2,Flags字段添加RPC_QUERY_CLIENT_PRINCIPAL_NAME标记 - 传入持有的
RPC_BINDING_HANDLE和结构指针调用函数,返回后结构的ClientPrincipalName字段就直接存储了客户端的用户名字符串,不需要额外做SID转用户名的操作
- 实例化
- 如果需要获取SID等更细粒度的安全信息,改用
RPC_CALL_ATTRIBUTES_V3_W结构:
将结构Version设为3,Flags添加RPC_QUERY_ACCESS_TOKEN标记,调用后会直接返回客户端的只读模拟令牌句柄,你可以直接用这个令牌查询SID、权限组等信息,用完调用CloseHandle释放即可,全程不需要切换当前线程的执行上下文。
关于模拟方案的补充说明
如果需要兼容Windows 2000及更早的不支持上述查询接口的系统,用模拟方案也完全不存在“重量级”的问题,只要按如下写法保证状态一定恢复即可:
RpcStatus status = RpcImpersonateClient(hBinding); if (status == RPC_S_OK) { __try { // 执行获取用户名、SID的逻辑 } __finally { RpcRevertToSelfEx(hBinding); } }
注意优先用
RpcRevertToSelfEx而非旧版RpcRevertToSelf,前者绑定指定的RPC绑定句柄做上下文恢复,就算存在嵌套RPC调用的模拟场景,也不会错误恢复其他上下文,单次模拟+恢复的总耗时在百纳秒级,对业务逻辑几乎无影响。
内容的提问来源于stack exchange,提问作者Sergey Kolesnik
相关产品推荐
相关产品推荐

