使用Windows凭据管理器

时间:2018-02-01 17:22:58

标签: delphi

我从SO获得这个Delphi代码似乎非常简单。我添加了一些缺失的类型并替换了一些缺少的字符串处理函数,并得到了这个。

unit WinCred;

interface

uses
  Windows, SysUtils;

type
  CREDENTIAL_ATTRIBUTE = packed record
    Keyword: LPTSTR;
    Flags: DWORD;
    ValueSize: DWORD;
    Value: LPBYTE;
  end;
  PCREDENTIAL_ATTRIBUTE = ^CREDENTIAL_ATTRIBUTE;

  CREDENTIALW = packed record
    Flags: DWORD;
    Type_: DWORD;
    TargetName: LPTSTR;
    Comment: LPTSTR;
    LastWritten: FILETIME;
    CredentialBlobSize: DWORD;
    CredentialBlob: LPBYTE;
    Persist: DWORD;
    AttributeCount: DWORD;
    Attributes: PCREDENTIAL_ATTRIBUTE;
    TargetAlias: LPTSTR;
    UserName: LPTSTR;
  end;
  PCREDENTIALW = ^CREDENTIALW;

function CredWriteW(Credential: PCREDENTIALW; Flags: DWORD): Boolean; stdcall; external 'Advapi32.dll';

function CredWriteGenericCredentials(const Target, Username, Password: UnicodeString): Boolean;

implementation

function CredWriteGenericCredentials(const Target, Username, Password: UnicodeString): Boolean;
var
    Credentials: CREDENTIALW;
begin
    ZeroMemory(@Credentials, SizeOf(Credentials));
    Credentials.TargetName := PWideChar(Target); //cannot be longer than CRED_MAX_GENERIC_TARGET_NAME_LENGTH (32767) characters. Recommended format "Company_Target"
    Credentials.Type_ := CRED_TYPE_GENERIC;
    Credentials.UserName := PWideChar(Username);
    Credentials.Persist := CRED_PERSIST_LOCAL_MACHINE;
    Credentials.CredentialBlob := PByte(Password);
    Credentials.CredentialBlobSize := 2*(Length(Password)); //By convention no trailing null. Cannot be longer than CRED_MAX_CREDENTIAL_BLOB_SIZE (512) bytes
    Result := CredWriteW(@Credentials, 0);
end;

end.

然而,当我测试这个功能时

[Test]
[TestCase('user', 'pass')]
procedure TestInsertCred(Username, password: string);

...

procedure TWinCredTests.TestInsertCred(Username, password: string);
begin
  Assert.IsTrue(CredWriteGenericCredentials('WinCred_Test', Username, password));
end;

密码显示在用户名中。

enter image description here

令我感到困惑。 .Username字段不应该使用用户名吗?密码写入" credentialBlob"?我已经检查了所有功能签名,以确保我没有错误地切换过。

1 个答案:

答案 0 :(得分:4)

假设您正在使用DUnitX,TestCase属性的第一个参数是测试用例名称,后跟参数。因此,您要定义一个名为' user'的测试用例,并将其传递给'传递'作为UserName而没有密码。 试试这个:

[TestCase('TestInsertCred', 'user,pass')]