本質的にローカルWebサーバーとして機能するサービスを作成しようとしています。理論的には、ユーザーはブラウザでlocalhostを使用して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
@ ConstantinLこの手法を試しましたが、サービスのSIDとユーザー名がありました。ユーザーのSIDおよび/またはユーザー名を返すために必要なアクセス権を知っていますか? – David