我正在嘗試創建基本上充當本地Web服務器的服務。理論上,用戶將通過在瀏覽器中通過本地主機訪問URI來使用REST API,即http://localhost:2017/path/to/function/call將連接到該服務並執行一個功能。如何獲取在C++中使用我的服務的用戶的SID和用戶名
我的問題是如何獲取調用該服務的帳戶的SID和用戶名?
我已經實現了幾個解決方案,但它們返回服務的SID和用戶名,而不是使用它的用戶。
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;
}
TCP/IP是匿名的,你將需要在你的服務器中實現驗證,即提示輸入用戶名和密碼。 –
不確定有關確切的條件,但如果您需要唯一登錄用戶的SID,則可以使用WTSGetActiveConsoleSessionId和WTSQueryUserToken獲取用戶令牌,然後使用GetTokenInformation獲取SID。但是您需要適當的訪問權限來執行此操作。 – KonstantinL
@KonstantinL我確實嘗試了這種技術,但它導致了服務的SID和用戶名。你知道什麼訪問權限才能使其返回用戶的SID和/或用戶名嗎? – David