C++ 如何在C+中获取使用我的服务的用户的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

我正在尝试创建一个服务,该服务基本上将充当本地web服务器。理论上,用户将通过浏览器中的localhost访问URI来使用REST API,即连接到服务并执行功能

我的问题是如何获取调用该服务的帐户的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;
}
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上登录的服务器计算机