在Windows客户端开发时,如果需要用户进行登录,那么很多时候都需要对用户密码进行保存。尤其是需要自动登录的时候!
一般来说,可能会使用ini文件进行用户名密码的保存。稍有安全意识的,会对用户名密码进行加密,再保存。下面要介绍的是另一种保存用户名密码的实现方式:windows系统上的PCREDENTIALW(附赠string与wstring互转的代码)。示例代码如下:
#include <Windows.h>
#include <wincred.h>
#include <string>
#include <tchar.h>
//s2ws
std::wstring s2ws(const char* pStr, int len, unsigned int CodePage = CP_ACP)
{
std::wstring buf;
if(pStr == NULL || (len < 0 && len != -1))
{
return buf;
}
// figure out how many wide characters we are going to get
int nChars = MultiByteToWideChar( CodePage, 0, pStr, len, NULL, 0 );
if ( len == -1 )
--nChars;
if ( nChars == 0 )
return L"";
// convert the narrow string to a wide string
// nb: slightly naughty to write directly into the string like this
buf.resize( nChars );
MultiByteToWideChar( CodePage, 0, pStr, len, const_cast<wchar_t*>(buf.c_str()), nChars );
return buf;
}
//ws2s
std::string ws2s(const wchar_t* pStr, int len, unsigned int CodePage = CP_ACP)
{
std::string buf;
if(pStr == NULL || (len < 0 && len != -1))
{
return buf;
}
// figure out how many narrow characters we are going to get
int nChars = WideCharToMultiByte( CodePage, 0, pStr, len, NULL, 0, NULL, NULL );
if ( len == -1 )
--nChars;
if ( nChars == 0 )
return "";
// convert the wide string to a narrow string
// nb: slightly naughty to write directly into the string like this
buf.resize( nChars );
WideCharToMultiByte( CodePage, 0, pStr, len, const_cast<char*>(buf.c_str()), nChars, NULL, NULL );
return buf;
}
bool WriteAccount(const std::string& username, const std::string& password)
{
char password_chars[255] = { 0 };
wchar_t username_wstrs[255] = { 0 };
wchar_t target_name_wstrs[1024] = { 0 };
// password
strcpy(password_chars, password.c_str());
DWORD cbCreds = 1 + strlen(password_chars);
// username
std::wstring username_wstr = s2ws(username.c_str(), strlen(username.c_str()));
wcscpy(username_wstrs, username_wstr.c_str());
// target name
std::wstring target_name_wstr = L"YourAppName";
wcscpy(target_name_wstrs, target_name_wstr.c_str());
CREDENTIALW cred = { 0 };
cred.Type = CRED_TYPE_GENERIC;
cred.TargetName = target_name_wstrs;
cred.CredentialBlobSize = cbCreds;
cred.CredentialBlob = (LPBYTE)password_chars;
cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
cred.UserName = username_wstrs;
return ::CredWriteW(&cred, 0);
}
bool ReadAccount(std::string& username, std::string& password)
{
wchar_t username_wstrs[255] = { 0 };
wchar_t target_name_wstrs[1024] = { 0 };
// target name
std::wstring target_name_wstr = L"YourAppName";
PCREDENTIALW pcred;
BOOL success = false;
do {
success = ::CredReadW(target_name_wstr.c_str(), CRED_TYPE_GENERIC, 0, &pcred);
if (!success)
{
break;
}
std::wstring wszUserName = std::wstring(pcred->UserName);
username = ws2s(wszUserName.c_str(), wcslen(wszUserName.c_str()));
std::string pwd((char*)pcred->CredentialBlob, pcred->CredentialBlobSize);
password = pwd;
::CredFree(pcred);
return true;
} while (0);
return false;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::string szUserName = "admin";
std::string szPassWord = "helloworld123456";
WriteAccount(szUserName, szPassWord);
std::string szUserNameOut;
std::string szPassWordOut;
ReadAccount(szUserNameOut, szPassWordOut);
printf("username : %s, password : %s\r\n", szUserNameOut.c_str(), szPassWordOut.c_str());
system("pause");
return 0;
}