1. 程式人生 > >Windows客戶端開發--通過CREDENTIAL儲存使用者名稱和密碼

Windows客戶端開發--通過CREDENTIAL儲存使用者名稱和密碼

                     

做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;    }  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

方案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();
  • 1
  • 2
  • 3
  • 4
  • 5

方案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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

我們注意關注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.

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);
  • 1
  • 2
  • 3
  • 4

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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

儲存使用者名稱和密碼

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);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

讀取使用者名稱和密碼

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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27