您的位置:首页 > 其它

Windows客户端开发--通过CREDENTIAL保存用户名和密码

2016-12-08 23:44 591 查看
做windows客户端,尤其是c/s开发,几乎都要接触到用户的登录。需要用户名和密码,那么我们往往要对用户名和密码就行保存。

方案1:写入ini配置文件

用过配置文件保存用户名和密码,密码肯定是不能实明文了,需要采用一定的加密算法。

但是,这是最大的麻烦,就是很容易被破解,反加密,得到用户的密码。

如何读取ini文件,请看:http://blog.csdn.net/wangshubo1989/article/details/47255823

方案2:写入数据口

可以通过写入数据库的方法,比如写入sqlite。

弊端和写入ini大差不差,就是容易被破解。

std::string last_name;
bool success = accounts_tb_->Get(kLastUserNameSqlKey, &last_name);
if (success)
{
if (!last_name.empty()) {
return last_team_from_cache;
}
}


方案3:qt中的QSettings

在qt中,我们可以使用QSettings来保存用户名和密码:

const static QString SETTING_ACCOUNT_ID = "account_id";
QSettings *settings = new QSettings();
settings->setValue(SETTING_ACCOUNT_ID, id);

QString id = settings->value(SETTING_ACCOUNT_ID, "").toString();


方案4:windows系统上的PCREDENTIALW

文件夹:

WinCred.h

PCREDENTIALW介绍:

The CREDENTIAL structure contains an individual credential.

原型:

typedef struct _CREDENTIAL {
DWORD                 Flags;
DWORD                 Type;
LPTSTR                TargetName;
LPTSTR                Comment;
FILETIME              LastWritten;
DWORD                 CredentialBlobSize;
LPBYTE                CredentialBlob;
DWORD                 Persist;
DWORD                 AttributeCount;
PCREDENTIAL_ATTRIBUTE Attributes;
LPTSTR                TargetAlias;
LPTSTR                UserName;
} CREDENTIAL, *PCREDENTIAL;


我们注意关注UserName和CredentialBlob:

CredentialBlob

Secret data for the credential. The CredentialBlob member can be both read and written.

If the Type member is CRED_TYPE_DOMAIN_PASSWORD, this member contains the plaintext Unicode password for UserName. The CredentialBlob and CredentialBlobSize members do not include a trailing zero character. Also, for CRED_TYPE_DOMAIN_PASSWORD, this member can only be read by the authentication packages.

If the Type member is CRED_TYPE_DOMAIN_CERTIFICATE, this member contains the clear test Unicode PIN for UserName. The CredentialBlob and CredentialBlobSize members do not include a trailing zero character. Also, this member can only be read by the authentication packages.

If the Type member is CRED_TYPE_GENERIC, this member is defined by the application.

Credentials are expected to be portable. Applications should ensure that the data in CredentialBlob is portable. The application defines the byte-endian and alignment of the data in CredentialBlob.

UserName

The user name of the account used to connect to TargetName.

If the credential Type is CRED_TYPE_DOMAIN_PASSWORD, this member can be either a DomainName\UserName or a UPN.

If the credential Type is CRED_TYPE_DOMAIN_CERTIFICATE, this member must be a marshaled certificate reference created by calling CredMarshalCredential with a CertCredential.

If the credential Type is CRED_TYPE_GENERIC, this member can be non-NULL, but the credential manager ignores the member.

This member cannot be longer than CRED_MAX_USERNAME_LENGTH (513) characters.

更多的资料去看看msdn:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx

CredWrite函数

作用:

The CredWrite function creates a new credential or modifies an existing credential in the user’s credential set.

原型:

BOOL CredWrite(
_In_ PCREDENTIAL Credential,
_In_ DWORD       Flags
);


CredRead函数

作用:

The CredRead function reads a credential from the user’s credential set.

原型:

BOOL CredRead(
_In_  LPCTSTR     TargetName,
_In_  DWORD       Type,
_In_  DWORD       Flags,
_Out_ PCREDENTIAL *Credential
);


保存用户名和密码

bool SaveAccount(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 = nbase::UTF8ToUTF16(username);
wcscpy(username_wstrs, username_wstr.c_str());

// target name
std::wstring target_name_wstr = L"MyApp";
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 GetAccount(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"MyApp";

PCREDENTIALW pcred;

BOOL success = false;
do {
success = ::CredReadW(target_name_wstr.c_str(), CRED_TYPE_GENERIC, 0, &pcred);
if (!success)
{
break;
}
username = nbase::UTF16ToUTF8(pcred->UserName);

std::string pwd((char*)pcred->CredentialBlob, pcred->CredentialBlobSize);
password = pwd;
::CredFree(pcred);
return true;
} while (0);

return false;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: