C#使用SecureString调用LogonUser失败

时间:2015-01-14 11:29:27

标签: c# security winapi

每个人,我都面临着LogonUser功能的问题。

我只想知道是否可以通过此签名将LogonUser函数导入C#:

[DllImport("advapi32.dll", SetLastError = true)]
internal static extern int LogonUser(string username, string domain, IntPtr password, int logonType, int logonProvider, ref IntPtr token);

因为我想保护我的密码不使用字符串,而是使用SecureString类。然后使用如下函数:

var passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password);
var result = LogonUser(userName, domain, passwordPtr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token);

我总是得到result = 0,并且消息显示用户名和密码不正确。 但是当我更改签名以使用字符串密码时,一切都运行良好。

请帮助我保护密码SecureString对我来说非常重要。

1 个答案:

答案 0 :(得分:2)

正如Alex K所指出的那样,在SecureStringToGlobalAllocUnicode中使用LogonUser就是一个例子。请注意,P / Invoke声明有:

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String username, String domain, IntPtr password,
            int logonType, int logonProvider, ref IntPtr token);

已指定CharSet = CharSet.Unicode。很遗憾,由于历史原因,默认的CharSet值为Ansi,因此您的 P / Invoke尝试将使用该值。

这适用于username参数,因为P / Invoke基础结构将确保它适当地转换string。但它不适用于password参数,因为您已经已经执行了字符串转换,并且您已将其作为Unicode完成 - 并且所有P / Invoke现在看到的是IntPtr

我建议更新您的P / Invoke签名以匹配样本中给出的签名。


另一种选择是切换到使用SecureStringToGlobalAllocAnsi并单独保留P / Invoke签名。但这是一个严重的二流解决方案。严重不建议在2015年编写非Unicode认知代码。

养成始终在您编写的任何P / Invoke签名中指定CharSet.Unicode的习惯。