在我的WPF应用程序中,我希望允许管理员使用集成安全性为各种其他用户测试数据库连接 . 所以我有一个表单,允许管理员输入域名,用户名和密码,然后测试它 . 我能够安全地处理密码,直到我在 advapi32.dll
中调用 LogonUser
,这需要 string password
LogonUser(UserName, Domain, Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref UserHandle)
我编写了一个实用程序函数,它将SecureString转换为尽可能安全的字符串,然后在LogonUser调用中将其调用密码:
LogonUser(UserName, Domain, Helper.ConvertSafely(Password), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref UserHandle)
由于LogonUser的签名采用字符串,除非LogonUser在执行时正确地处理密码,否则在调用返回后它仍然可以在我的调用堆栈中以纯文本形式存在 . 是否有一种更安全的方式来冒充用户,在这种情况下,我可以确信PW一直是安全的?
基本上我只需要一个 WindowsImpersonationContext
但是我想在没有密码的情况下以纯文本形式获取它 .
3 回答
如果您要模拟的用户已登录计算机(例如在另一个会话中),则答案如下:Is it possible for a Windows service impersonate a user without a password?
如果他's not, you'将不得不为LogonUser提供密码 . 此密码必须至少驻留在内存中,因为这是LogonUser的定义方式 . 请注意,并非所有身份验证包都需要密码(如生物识别或智能卡:Windows Authentication Overview) .
所以,如果你真的想要模仿,那么你可以从某个地方获得微软的代码:Marshal.SecureStringToGlobalAllocUnicode Method sample code
你真的不能做得更多 .
在托管应用程序中,您可以使用SecureString类来处理敏感信息 . 通常不需要滚动自己的安全字符串机制 .
在您进入LogonUser之前,您将传递SecureString密码的非托管副本 . 您可以使用
Marshal.SecureStringToGlobalAllocUnicode
方法 . 因此,您的应用程序域中永远不会有代表密码的托管对象 .您可以在this文章中找到示例代码 .
如果您需要更高的安全性,我建议您禁止从您的wpf客户端直接连接数据库 . 您可以引入中间层 . 因此,安全性从客户端转移到这个服务器 . 客户端和App-Server之间的通信已加密,只有应用服务器与数据库通信 .
更新:
您可以实现加密的
app.config
. 您可以通过几种不同的方法来实现:Protecting Connection Information
Windows Data Protection
那么这是如何工作的,当管理员插入凭证时,您将使用新凭证解密
app.config
修改密钥/值 . 然后一旦插入它再次加密配置文件 .所以它暴露的最低限度,但数据也通过封装插入,这也有助于隐藏它 .
这是一种方法,虽然
SecureString
将起作用,它期望char[]
. 在某些情况下,当通过advapi32.dll
进行接口时,这可能并不理想 .