C++ 如何在C+中获取使用我的服务的用户的SID和用户名+;
我正在尝试创建一个服务,该服务基本上将充当本地web服务器。理论上,用户将通过浏览器中的localhost访问URI来使用REST API,即连接到服务并执行功能 我的问题是如何获取调用该服务的帐户的SID和用户名 我已经实现了几个解决方案,但是它们返回服务的SID和用户名,而不是使用它的用户C++ 如何在C+中获取使用我的服务的用户的SID和用户名+;,c++,windows,winapi,C++,Windows,Winapi,我正在尝试创建一个服务,该服务基本上将充当本地web服务器。理论上,用户将通过浏览器中的localhost访问URI来使用REST API,即连接到服务并执行功能 我的问题是如何获取调用该服务的帐户的SID和用户名 我已经实现了几个解决方案,但是它们返回服务的SID和用户名,而不是使用它的用户 OJSon* UnifiedStreamingService::getUserDetails() { OJSon* result = OJSon::create(); if(result
OJSon* UnifiedStreamingService::getUserDetails()
{
OJSon* result = OJSon::create();
if(result)
{
/*
HANDLE hToken = NULL;
ULONG id = WTSGetActiveConsoleSessionId();
BOOL bRet = WTSQueryUserToken(id, &hToken);
if (bRet == false)
{
DWORD error = GetLastError();
printf("ERROR: %d", error);
}
*/
HANDLE hToken = NULL;
if ( ! OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )
{
//_tprintf( _T("OpenProcessToken failed. GetLastError returned: %d\n"), GetLastError());
return NULL;
}
// Get the size of the memory buffer needed for the SID
DWORD dwBufferSize = 0;
if ( ! GetTokenInformation( hToken, TokenUser, NULL, 0, &dwBufferSize ) && ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) )
{
//_tprintf( _T("GetTokenInformation failed. GetLastError returned: %d\n"), GetLastError());
// Cleanup
CloseHandle( hToken );
hToken = NULL;
return NULL;
}
// Allocate buffer for user token data
std::vector<BYTE> buffer;
buffer.resize( dwBufferSize );
PTOKEN_USER pTokenUser = reinterpret_cast<PTOKEN_USER>( &buffer[0] );
// Retrieve the token information in a TOKEN_USER structure
if ( ! GetTokenInformation(
hToken,
TokenUser,
pTokenUser,
dwBufferSize,
&dwBufferSize))
{
//_tprintf( _T("2 GetTokenInformation failed. GetLastError returned: %d\n"), GetLastError());
// Cleanup
CloseHandle( hToken );
hToken = NULL;
return NULL;
}
// Check if SID is valid
if ( ! IsValidSid( pTokenUser->User.Sid ) )
{
//_tprintf( _T("The owner SID is invalid.\n") );
// Cleanup
CloseHandle(hToken);
hToken = NULL;
return NULL;
}
// add the name
OString* name = lookupAccountSid(pTokenUser->User.Sid);
if(name)
{
result->setKey(&OString("name"), name);
SAFEDELETE(name);
}
// add the SID
OString* sid = convertSidToString(pTokenUser->User.Sid);
if(sid)
{
result->setKey(&OString("SID"), sid);
SAFEDELETE(sid);
}
// Cleanup
CloseHandle(hToken);
hToken = NULL;
}
return result;
}
OString* UnifiedStreamingService::convertSidToString(PSID pSID)
{
OString* result = NULL;
if(pSID)
{
// Get string corresponding to SID
LPTSTR pszSID = NULL;
if ( ! ConvertSidToStringSid( pSID, &pszSID ) )
{
return NULL;
}
result = new OString(pszSID);
// Release buffer allocated by ConvertSidToStringSid API
LocalFree( pszSID );
pszSID = NULL;
}
return result;
}
OString* UnifiedStreamingService::lookupAccountSid(PSID pSID)
{
DWORD dwSize = 256;
DWORD dwResult = 0;
SID_NAME_USE SidType;
LPTSTR lpName = new TCHAR[dwSize];
LPWSTR lpDomain = new TCHAR[dwSize];
OString* result = NULL;
if( !LookupAccountSid( NULL, pSID, lpName, &dwSize, lpDomain, &dwSize, &SidType ) )
{
dwResult = GetLastError();
return NULL;
}
OString* pDomain = new OString(lpDomain);
OString* pName = new OString(lpName);
if(pDomain && pName)
{
result = OString::createByFormat(&OString("%s\\%s"), pDomain, pName);
SAFEDELETE(pDomain);
SAFEDELETE(pName);
}
delete[] lpDomain;
delete[] lpName;
return result;
}
OJSon*UnifiedStreamingService::getUserDetails()
{
OJSon*result=OJSon::create();
如果(结果)
{
/*
句柄hToken=NULL;
ULONG id=WTSGetActiveConsoleSessionId();
BOOL-bRet=WTSQueryUserToken(id和hToken);
if(bRet==false)
{
DWORD error=GetLastError();
printf(“错误:%d”,错误);
}
*/
句柄hToken=NULL;
if(!OpenProcessToken(GetCurrentProcess()、TOKEN\u QUERY和hToken))
{
//_tprintf(_T(“OpenProcessToken失败。GetLastError返回:%d\n”),GetLastError();
返回NULL;
}
//获取SID所需的内存缓冲区大小
DWORD dwBufferSize=0;
如果(!GetTokenInformation(hToken、TokenUser、NULL、0和dwBufferSize)&&(GetLastError()!=错误\u缓冲区不足))
{
//_tprintf(_T(“GetTokenInformation失败。GetLastError返回:%d\n”),GetLastError();
//清理
闭合手柄(hToken);
hToken=NULL;
返回NULL;
}
//为用户令牌数据分配缓冲区
向量缓冲区;
调整缓冲区大小(dwBufferSize);
PTOKEN_USER pTokenUser=reinterpret_cast(&buffer[0]);
//检索令牌用户结构中的令牌信息
如果(!GetTokenInformation(
赫托肯,
令牌用户,
托肯努塞,
dws大小,
&dwBufferSize)
{
//_tprintf(_T(“2 GetTokenInformation失败。GetLastError返回:%d\n”),GetLastError();
//清理
闭合手柄(hToken);
hToken=NULL;
返回NULL;
}
//检查SID是否有效
如果(!IsValidSid(pTokenUser->User.Sid))
{
//_tprintf(_T(“所有者SID无效。\n”));
//清理
闭合手柄(hToken);
hToken=NULL;
返回NULL;
}
//添加名称
OString*name=lookupAccountSid(pTokenUser->User.Sid);
如果(姓名)
{
结果->设置键(&OString(“名称”),名称);
删除(姓名);
}
//添加SID
OString*sid=convertSidToString(pTokenUser->User.sid);
如果(sid)
{
结果->设置键(&OString(“SID”),SID);
安全删除(sid);
}
//清理
闭合手柄(hToken);
hToken=NULL;
}
返回结果;
}
OString*UnifiedStreamingService::convertSidToString(PSID PSID)
{
OString*result=NULL;
if(pSID)
{
//获取与SID对应的字符串
LPTSTR pszSID=NULL;
if(!ConvertSidToStringSid(pSID和pszSID))
{
返回NULL;
}
结果=新的OString(pszSID);
//释放ConvertSidtoString API分配的缓冲区
LocalFree(pszSID);
pszSID=NULL;
}
返回结果;
}
OString*UnifiedStreamingService::lookupAccountSid(PSID PSID)
{
DWORD dwSize=256;
DWORD dwResult=0;
SID\u名称\u使用SidType;
LPTSTR lpName=new TCHAR[dwSize];
LPWSTR lpDomain=new TCHAR[dwSize];
OString*result=NULL;
if(!LookupAccountSid(NULL、pSID、lpName、&dwSize、lpDomain、&dwSize、&SidType))
{
dwResult=GetLastError();
返回NULL;
}
OString*pDomain=新的OString(lpDomain);
OString*pName=新OString(lpName);
if(pDomain&&pName)
{
结果=OString::createByFormat(&OString(“%s\\%s”)、pDomain、pName);
安全删除(pDomain);
安全删除(pName);
}
删除[]域;
删除[]lpName;
返回结果;
}
通过使用WTSGetActiveConsoleSessionId和WTSQueryUserToken获取用户令牌,然后使用GetTokenInformation获取SID,可以完成该任务。
附加要求是服务在本地系统帐户下运行,该帐户授予SE_TCB_NAME privilege(=SeTcbPrivilege)。所需的SE_TCB_名称。请注意,其他帐户通常没有seu TCB_NAME privilege TCP/IP是匿名的,您需要在服务器中实现身份验证,即提示输入用户名和密码。不确定具体条件,但如果您需要唯一登录用户的SID,则可以使用WTSGetActiveConsoleSessionId和WTSQueryUserToken获取用户令牌,然后使用GetTokenInformation获取SID。但您需要适当的访问权限才能执行此操作。@KonstantinL我确实尝试过这种技术,但它产生了服务的SID和用户名。您知道需要什么访问权限才能使其返回用户的SID和/或用户名吗?嗯。。有点不对劲。如果权限不足,您应该获得零句柄,而不是服务句柄。你能出示你的代码吗?@KonstantinL嗨,我已经附上了我当前的代码。好的,OP明确地说用户将使用
localhost
URL,这样这个答案就可以接受了。但您至少应该警告,您正在提供服务运行所在机器上当前会话的URL(如果有的话)。因此,如果machineA中的clientA连接到userB运行的machineB服务(您将得到userB),它将不会给出预期的结果。如果在machineB上的userC下运行的计划任务连接到machineB上的服务:仍然获取UserB,则此方法不考虑:1)具有多个用户在sam上登录的服务器计算机