最近在开发远程控制项目(类似teamviewer),但希望能直接使用windows用户名和密码进行用户验证,因此需要能验证外部输入的用户名和密码是否正确。本文分享具体方法
方法一、使用登陆函数验证
#include "windows.h" #include "wtsapi32.h" #include "Lmcons.h" bool CheckUserPwd(const char* pwd, const char* user = nullptr) { char _user[UNLEN + 1]; if (user != nullptr) { strcpy(_user, user); } else { char* _username; DWORD infoSize = 0; //获取当前登录用户名 WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTS_INFO_CLASS::WTSUserName, &_username, &infoSize); strcpy(_user, _username); WTSFreeMemory(_username); } HANDLE hToken; BOOL blogon = LogonUserA(_user, ".", pwd, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken); if (blogon) { CloseHandle(hToken); } return blogon; }
LogonUserA函数使用用户名和密码尝试登录操作;从API说明看,该函数仅仅获取Token,并不运行其它进程;如果仅仅验证用户名密码,LOGON32_LOGON_NETWORK模式权限较低,建议使用
方法二、使用修改密码函数验证
#include <stdio.h> #include "windows.h" #include "Lm.h" bool CheckUserPwd(const char* pwd) { TCHAR userName[64] = { 0 }; DWORD dwSize = MAX_PATH; GetUserNameA(userName, &dwSize); //%hs格式见参考资料 WCHAR wUserName[64]; swprintf(wUserName, sizeof(wUserName), L"%hs", userName); WCHAR wPwd[64]; swprintf(wPwd, sizeof(wPwd), L"%hs", pwd); NET_API_STATUS dwStatus; dwStatus = NetUserChangePassword(NULL, wUserName, wPwd, wPwd); if ((dwStatus == NERR_Success) || (dwStatus == NERR_PasswordTooShort)) { return true; } return false; }
两种方法的差异
项目最后选取了方法一
1、NetUserChangePassword函数如果在已登陆用户的环境中可以正确运行,如果在系统服务中执行失败;估计是windows权限限制导致
2、NetUserChangePassword函数几秒后才返回错误,LogonUserA执行速度快