C#调用登录用户失败,带有SecureString
各位,我面临着C#调用登录用户失败,带有SecureString,c#,security,winapi,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); 因为我想保护
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
保护密码,这对我很重要。正如Alex K所指出的,在中有一个使用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
。不幸的是,由于历史原因,默认值是Ansi
,因此您的P/Invoke尝试将使用该值
这对于username
参数很好,因为p/Invoke基础结构将确保它适当地转换字符串。但是它不适合于password
参数,因为您已经执行了字符串转换,并且已经以Unicode的形式完成了转换,而P/Invoke现在看到的只是IntPtr
我建议更新您的p/Invoke签名以匹配示例中给出的签名
另一种选择是切换到使用p/Invoke签名,而不使用p/Invoke签名。但这是一个严重的二流解决方案。不建议在2015年编写非Unicode代码
只要养成习惯,在您编写的任何p/Invoke签名中始终指定CharSet.Unicode
。这就是您应该做的。。SecureStringToGlobalAllocUnicode
的MSDN页面有一个调用LogonUser
的完整示例:一个明显的问题是,如果您的P/Invoke签名错误,并且试图将Unicode文本传递到Ansi版本的LogonUser
,但我不能肯定,因为您没有显示P/Invoke签名。我刚刚更新了签名。感谢Damien_the_unsiver和Alex K。我尝试用字符集将签名更新为Unicode,现在工作正常。我只是没有意识到这个设置,并且在Alex K提到的文章中多次比较了函数签名:)