【问题标题】:CredUIPromptForCredentials from .NET with SecureString来自 .NET 的 CredUIPromptForCredentials 和 SecureString
【发布时间】:2013-04-14 13:29:11
【问题描述】:

我想显示标准系统对话框,要求用户输入帐户用户名和密码,以使用此信息启动具有这些凭据的进程。

我被指向显示该对话框的CredUIPromptForCredentials 函数。它以字符串形式返回用户名和密码。但是ProcessStartInfo 结构需要密码为SecureString

我知道我现在可以将密码用作字符串并将其逐个字符地转换为 SecureString(没有单独的函数) - 但它会完全破坏 SecureString 背后的想法。

所以我想必须有某种方法可以直接接受来自 .NET 中对CredUIPromptForCredentials 的非托管调用的密码作为SecureString。毕竟,我真的不需要以任何方式访问我的应用程序中的密码。它只是应该用于启动另一个进程,然后可以尽快忘记。

那么我的CredUIPromptForCredentials 的 P/Invoke 声明与SecureString 的外观如何? (我从 pinvoke.net 的 C# 开始。)

更新:哦,如果有人有 Windows Vista/7 中新功能 CredUIPromptForWindowsCredentials 的示例,那也很酷,因为我什至不知道如何暂时使用它。

【问题讨论】:

标签: c# pinvoke securestring


【解决方案1】:

您可以将非托管字符串缓冲区的IntPtr 强制转换为char* 并使用SecureString(char*, int) 构造函数。

// somehow, we come into posession of an IntPtr to a string
// obviously, this would be a foolish way to come into it in
// production, since stringOriginalContents is already in managed
// code, and the lifetime can therefore not be guaranteed...
var stringOriginalContents = "foobar";
IntPtr strPtr = Marshal.StringToHGlobalUni(stringOriginalContents);
int strLen = stringOriginalContents.Length;
int maxLen = 100;

// we copy the IntPtr to a SecureString, and zero out the old location
SecureString ssNew;
unsafe
{
    char* strUPtr = (char*)strPtr;

    // if we don't know the length, calculate
    //for (strLen = 0; *(strUPtr + strLen) != '\0' 
    //    // stop if the string is invalid
    //    && strLen < maxLen; strLen++)
    //    ;

    ssNew = new SecureString((char*)strPtr, strLen);

    // zero out the old memory and release, or use a Zero Free method
    //for (int i = 0; i < strLen; i++)
    //    *(strUPtr + i) = '\0';
    //Marshal.FreeHGlobal(strPtr);
    // (only do one of these)
    Marshal.ZeroFreeGlobalAllocUnicode(strPtr);
}

// now the securestring has the protected data, and the old memory has been
// zeroed, we can check that the securestring is correct.  This, also should
// not be in production code.
string strInSecureString =
    Marshal.PtrToStringUni(
    Marshal.SecureStringToGlobalAllocUnicode(ssNew));
Assert.AreEqual(strInSecureString, stringOriginalContents);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    • 2010-09-13
    • 1970-01-01
    • 2019-02-12
    相关资源
    最近更新 更多