Window不同账户权限优缺点整理

来源:csdn博客 分类: 文章浏览史 发布时间:2023-10-05 17:34:13 最后更新:2023-10-05 浏览:291
转载声明:
本文为摘录自“csdn博客”,版权归原作者所有。
温馨提示:
为了更好的体验,请点击原文链接进行浏览
摘录时间:
2023-10-05 17:34:13



提示:以下是本篇文章正文内容,下面整理可供参考
PC端程序以管理员权限运行,想要做到在任意系统中开机自启动,经研究发现好像无法实现。
方案一:设置到启动项里。administrator账号登录系统的可以开机自启动,其他账号登录系统开启自启动全部失败。
方案二:做一个windows服务,服务启动PC端程序。服务可以开机自启动,但是服务启动的程序要么是system权限,要么是账户权限,无法保证以管理员权限运行。
以下是我在研究过程中总结的windows权限相关知识。

一、windows系统账户权限

Windows中权限指的是不同账户文件、文件夹、注册表等的访问能力。一般我们常用的权限分为普通账户权限、管理员账户权限和system账户权限。

二、权限优缺点

1. 普通账户权限

优点:
1.权限最小化原则,确保用户资源得到最大保障;
2.普通权限程序支持任意账户登录的开机自启动;
缺点:
1. 启动以管理员权限启动的程序时,会弹出用户账户控制(UAC)弹窗;
2. 无法访问服务列表,判断服务程序有没有启动;
3. 无法修改或删除Program Files等管理员权限路径下的文件,仅能查看;
4. 程序无法删掉以管理员权限运行的进程;

2、管理员权限

优点:
1. 可以访问服务列表,运行服务程序;
2. 可正常修改或删除访问Program Files等管理员权限路径下所有文件;
3. 可以启动普通权限运行的程序并赋予管理员权限;
缺点:
1. 普通账户登录的系统,无法开机自启动;
2. 程序无法杀掉system权限运行的进程;

3、system权限

优点:
1. 程序以windows服务托管运行,支持开机自启动;
2. 可以以用户登录账户权限或system权限启动动外部程序;
缺点:
1. system权限获取桌面路径、appdata路径时,默认访问的是system相关路径,不是当前桌面路径;
2. 程序不是在主线程中运行(很难理解)
3. 弹出选择路径弹窗时,会报错或者无法选择桌面路径;
4. 无法打开系统默认浏览器、文本编辑器等,因为程序运行权限超过系统登录账户范畴;

三、跨权限相关调用

1. 启动外部程序

需要注意普通权限调用以管理员权限运行的程序时,会弹出UAC弹窗

QString filePath = QString("D:123.exe");
//SW_SHOW:以正常窗口大小启动外部程序;SW_HIDE:以隐藏窗口启动外部程序
int ret = (int)ShellExecute(NULL, NULL, (LPCSTR)filePath.toLocal8Bit(), NULL, NULL, SW_SHOW);

2. system权限获取当前用户桌面路径

//首先获取当前用户登录token
static HANDLE GetCurrentLogonUserToken()
{
	//The following api call fails to get a valid session id if remote desktop /team viewer is running at startup
	UINT dwSessionId = WTSGetActiveConsoleSessionId();
	//LOG_DEBUG("Session id from WTSGetActiveConsoleSessionId:%d", dwSessionId);
	HANDLE hImpersonationToken = NULL;
	if (!WTSQueryUserToken(dwSessionId, &hImpersonationToken))
	{
		//LOG_ERROR("Exception in WTSQueryUserToken:%d Proceeding to enumerate sessions!", GetLastError());
	}
	else
	{
		//LOG_DEBUG("Returning WTSGetActiveConsoleSessionId Token:%d", hImpersonationToken);
		WCHAR* pUserName;
		DWORD user_name_len = 0;
		if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, dwSessionId, WTSUserName, &pUserName, &user_name_len))
		{
			//LOG_INFO("UserName from sessionId is %s:", pUserName);
			if (pUserName) {
				WTSFreeMemory(pUserName);
			}
			return hImpersonationToken;
		}
		else
		{
			//LOG_ERROR("Exception in WTSQuerySessionInformation:%d! Returning Null Impersonation Token", GetLastError());
			return NULL;
		}
	}

	DWORD sessionCount = 0;
	WTS_SESSION_INFOA* pSession = NULL;
	try {
		if (!WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &sessionCount))
		{
			//LOG_ERROR("WTSEnumerateSessionsA failed. errcode=%d", GetLastError());
			return NULL;
		}
	}
	catch (...) {}

	//LOG_INFO("Begin Enumerating Sesions : %d", sessionCount);
	DWORD sessionId = -1;
	for (DWORD i = 0; i < sessionCount; i++)
	{
		sessionId = pSession[i].SessionId;
		//LOG_DEBUG("SessionId:%d", sessionId);

		WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
		WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;

		DWORD bytes_returned = 0;
		if (::WTSQuerySessionInformation(
			WTS_CURRENT_SERVER_HANDLE,
			sessionId,
			WTSConnectState,
			reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
			&bytes_returned))
		{
			wts_connect_state = *ptr_wts_connect_state;
			::WTSFreeMemory(ptr_wts_connect_state);
			if (wts_connect_state != WTSActive)
			{
				//LOG_WARNING("wts_connect_state != WTSActive! Continuing ###");
				continue;
			}
		}
		else
		{
			//LOG_WARNING("Error in WTSQuerySessionInformation:%d: Continuing ###", GetLastError());
			continue;
		}
	}

	//LOG_INFO("session_id from enumerating sessions: %d, from WTSGetActiveConsoleSessionId:%d", sessionId, dwSessionId);
	if (sessionId == -1) {
		//LOG_ERROR("Fatal Error: Failed to get session_id by both methods");
		return NULL;
	}
	if (!WTSQueryUserToken(sessionId, &hImpersonationToken))
	{
		DWORD err = GetLastError();
		//LOG_ERROR("Fatal Error: Failed WTSQueryUserToken on enumerated sessionid: %d", err);
		return NULL;
	}


	// Get user name of this process
	//LPTSTR pUserName = NULL;
	WCHAR* pUserName;
	DWORD user_name_len = 0;
	if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &pUserName, &user_name_len))
	{
		//log username contained in pUserName WCHAR string
		// char * lpszUserName = WideCharToChar(pUserName);
		//LOG_INFO("UserName from session_id [after enumeration] is %s:", pUserName);
		if (pUserName) {
			WTSFreeMemory(pUserName);
		}
		return hImpersonationToken;
	}
	else
	{
		//LOG_ERROR("Exception in WTSQuerySessionInformation:%d! Returning Null Impersonation Token", GetLastError());
		return NULL;
	}
}
#include <ShlObj_core.h>
//然后根据token可以获取当前系统登录账户下桌面路径、appdata路径等
BROWSEINFOW bi;
wchar_t initPath[MAX_PATH];
initPath[0] = 0;
std::wstring wsValue = L"";
//CSIDL_DESKTOPDIRECTORY:桌面路径
//CSIDL_APPDATA:Application Data路径
//CSIDL_STARTMENU:Start Menu路径
if (SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_DESKTOPDIRECTORY, hToken, SHGFP_TYPE_DEFAULT, initPath))) {
	qDebug() << QString("get deskop success");
	wsValue = initPath;
}
QString path = QString::fromStdWString(wsValue);

3. system权限下启动外部程序

a. 以system权限启动外部程序
bool createProcessWithAdmin(DWORD& pid, const QString& strProcessName, const QString& pCmdLine /*= NULL*/)
{
	HANDLE hToken = NULL;
	HANDLE hTokenDup = NULL;
	LPVOID pEnv = NULL;
	pid = 0;

	if (strProcessName.isEmpty()) {
		return false;
	}

	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken)) {
		qDebug()<< QString("OpenProcessToken failed, errcode=%1").arg(GetLastError());
		return false;
	}
	do {
		//if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityIdentification, TokenPrimary, &hTokenDup))
		//{
		//	qDebug() << QString("DuplicateTokenEx failed, errcode=%1").arg(GetLastError());
		//	break;
		//}

		if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenPrimary, &hTokenDup))
		{
			CloseHandle(hToken);
			return false;
		}

		DWORD dwSessionId = WTSGetActiveConsoleSessionId();
		if (!SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD)))
		{
			qDebug()<<QString("SetTokenInformation failed");
			break;
		}

		if (!CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE)) {
			qDebug()<<QString("CreateEnvironmentBlock failed");
			break;
		}

		STARTUPINFO si;
		ZeroMemory(&si, sizeof(STARTUPINFO));
		si.cb = sizeof(STARTUPINFO);
		si.lpDesktop = "WinSta0\\Default";
		si.wShowWindow = SW_SHOW;
		si.dwFlags = STARTF_USESHOWWINDOW;
		PROCESS_INFORMATION pi;
		ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
		DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;

		if (!CreateProcessAsUser(hTokenDup,getTransCodeByteArray(strProcessName).data(), getTransCodeByteArray(pCmdLine).data(), NULL, NULL, FALSE, dwCreationFlag, pEnv, NULL, &si, &pi))
		{
			qDebug() << QString("CreateProcessAsUser failed, errcode=%1").arg(GetLastError());
			break;
		}

		//if (!CreateProcessAsUserW(hTokenDup, strProcessName.c_str(), pCmdLine, NULL, NULL, FALSE,dwCreationFlag,pEnv, NULL, &si, &pi))
		//{
		//	qDebug() << QString("CreateProcessAsUserW failed, errcode=%1").arg(GetLastError());
		//	break;
		//}

		CloseHandleSafe(pi.hProcess);
		CloseHandleSafe(pi.hThread);
		if (pEnv) {
			DestroyEnvironmentBlock(pEnv);
		}
		CloseHandleSafe(hToken);
		CloseHandleSafe(hTokenDup);
		pid = pi.dwProcessId;
		return true;
	} while (0);
	if (pEnv != NULL) {
		DestroyEnvironmentBlock(pEnv);
	}
	CloseHandleSafe(hTokenDup);
	CloseHandleSafe(hToken);
	return false;
}
b. 以当前用户登录权限启动外部程序
//首先获取当前用户令牌
static HANDLE GetCurrentLogonUserToken()
{
	//The following api call fails to get a valid session id if remote desktop /team viewer is running at startup
	UINT dwSessionId = WTSGetActiveConsoleSessionId();
	//LOG_DEBUG("Session id from WTSGetActiveConsoleSessionId:%d", dwSessionId);
	HANDLE hImpersonationToken = NULL;
	if (!WTSQueryUserToken(dwSessionId, &hImpersonationToken))
	{
		//LOG_ERROR("Exception in WTSQueryUserToken:%d Proceeding to enumerate sessions!", GetLastError());
	}
	else
	{
		//LOG_DEBUG("Returning WTSGetActiveConsoleSessionId Token:%d", hImpersonationToken);
		WCHAR* pUserName;
		DWORD user_name_len = 0;
		if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, dwSessionId, WTSUserName, &pUserName, &user_name_len))
		{
			//LOG_INFO("UserName from sessionId is %s:", pUserName);
			if (pUserName) {
				WTSFreeMemory(pUserName);
			}
			return hImpersonationToken;
		}
		else
		{
			//LOG_ERROR("Exception in WTSQuerySessionInformation:%d! Returning Null Impersonation Token", GetLastError());
			return NULL;
		}
	}

	DWORD sessionCount = 0;
	WTS_SESSION_INFOA* pSession = NULL;
	try {
		if (!WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &sessionCount))
		{
			//LOG_ERROR("WTSEnumerateSessionsA failed. errcode=%d", GetLastError());
			return NULL;
		}
	}
	catch (...) {}

	//LOG_INFO("Begin Enumerating Sesions : %d", sessionCount);
	DWORD sessionId = -1;
	for (DWORD i = 0; i < sessionCount; i++)
	{
		sessionId = pSession[i].SessionId;
		//LOG_DEBUG("SessionId:%d", sessionId);

		WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
		WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;

		DWORD bytes_returned = 0;
		if (::WTSQuerySessionInformation(
			WTS_CURRENT_SERVER_HANDLE,
			sessionId,
			WTSConnectState,
			reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
			&bytes_returned))
		{
			wts_connect_state = *ptr_wts_connect_state;
			::WTSFreeMemory(ptr_wts_connect_state);
			if (wts_connect_state != WTSActive)
			{
				//LOG_WARNING("wts_connect_state != WTSActive! Continuing ###");
				continue;
			}
		}
		else
		{
			//LOG_WARNING("Error in WTSQuerySessionInformation:%d: Continuing ###", GetLastError());
			continue;
		}
	}

	//LOG_INFO("session_id from enumerating sessions: %d, from WTSGetActiveConsoleSessionId:%d", sessionId, dwSessionId);
	if (sessionId == -1) {
		//LOG_ERROR("Fatal Error: Failed to get session_id by both methods");
		return NULL;
	}
	if (!WTSQueryUserToken(sessionId, &hImpersonationToken))
	{
		DWORD err = GetLastError();
		//LOG_ERROR("Fatal Error: Failed WTSQueryUserToken on enumerated sessionid: %d", err);
		return NULL;
	}
	// Get user name of this process
	//LPTSTR pUserName = NULL;
	WCHAR* pUserName;
	DWORD user_name_len = 0;
	if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &pUserName, &user_name_len))
	{
		//log username contained in pUserName WCHAR string
		// char * lpszUserName = WideCharToChar(pUserName);
		//LOG_INFO("UserName from session_id [after enumeration] is %s:", pUserName);
		if (pUserName) {
			WTSFreeMemory(pUserName);
		}
		return hImpersonationToken;
	}
	else
	{
		//LOG_ERROR("Exception in WTSQuerySessionInformation:%d! Returning Null Impersonation Token", GetLastError());
		return NULL;
	}
}
//以当前用户登录权限启动外部程序
bool createProcessWithUser(OUT DWORD& pid, const QString& strProcessName, const  QString& pCmdLine /*= NULL*/)
{
	HANDLE hToken = NULL;
	HANDLE hTokenDup = NULL;
	LPVOID pEnv = NULL;
	pid = 0;

		hToken = GetCurrentLogonUserToken();
		if (hToken == NULL) {
			qDebug() << QString("GetCurrentLogonUserToken failed, errcode=%1").arg(GetLastError());
			return false;
		}
		if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup))
		{
			qDebug() << QString("DuplicateTokenEx failed, errcode=%1").arg(GetLastError());
			return false;
		}

		DWORD dwSessionID = WTSGetActiveConsoleSessionId();
		if (!SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionID, sizeof(DWORD)))
		{
			qDebug() << QString("SetTokenInformation failed");
			return false;
		}
		if (!CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE))
		{
			qDebug() << QString("CreateEnvironmentBlock failed");
			return false;
		}

		STARTUPINFO si;
		ZeroMemory(&si, sizeof(STARTUPINFO));
		si.cb = sizeof(STARTUPINFO);
		si.lpDesktop = "WinSta0\\Default";
		si.dwFlags = STARTF_USESHOWWINDOW;
		si.wShowWindow = SW_SHOW;

		PROCESS_INFORMATION pi;
		ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
		DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
		if (!CreateProcessAsUser(hTokenDup, getTransCodeByteArray(strProcessName).data(), getTransCodeByteArray(pCmdLine).data(), NULL, NULL, FALSE,
			dwCreationFlags, pEnv, NULL, &si, &pi))
		{
			qDebug() << QString("CreateProcessAsUserW failed, errcode=%1").arg(GetLastError());
			return false;
		}

		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		if (pEnv != NULL) {
			DestroyEnvironmentBlock(pEnv);
		}
		CloseHandle(hTokenDup);
		CloseHandle(hToken);
		pid = pi.dwProcessId;
		return true;
	
	if (pEnv != NULL) {
		DestroyEnvironmentBlock(pEnv);
	}
	CloseHandleSafe(hTokenDup);
	CloseHandleSafe(hToken);
	return false;
}

总结

php技术微信