C# 调用 LogonUser 失败并返回 SecureString
C# Call LogonUser fail with SecureString
各位,我遇到了 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
class。然后稍后使用如下函数:
var passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password);
var result = LogonUser(userName, domain, passwordPtr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token);
我总是得到 result = 0 并且消息显示用户名和密码不正确。
但是当我将签名更改为使用字符串密码时,一切正常。
请帮助我保护密码 SecureString
对我来说很重要。
正如 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
的习惯。
各位,我遇到了 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
class。然后稍后使用如下函数:
var passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password);
var result = LogonUser(userName, domain, passwordPtr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token);
我总是得到 result = 0 并且消息显示用户名和密码不正确。 但是当我将签名更改为使用字符串密码时,一切正常。
请帮助我保护密码 SecureString
对我来说很重要。
正如 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
的习惯。