我知道您可以通过以下方式运行具有给定用户名/密码的进程:
var processInfo = new ProcessStartInfo
{
WorkingDirectory = workingDirectory,
FileName = "a name",
UserName = loggedUserName,
Password = "password",
Domain = userNameDomain,
UseShellExecute = false,
};
Process.Start(processInfo);
我面临的问题是我不想将实际密码写为代码的一部分,如果我将密码属性留空,则进程将无法启动...如何安全地启动进程没有将密码作为代码中的硬编码字符串公开?
答案 0 :(得分:7)
ProcessStartInfo.Password不是一个简单的字符串,您可以记下并分配给该属性。您需要的是SecureString实例,并且无法创建SecureString,将简单字符串传递给其构造函数。显然,操作系统没有API或方法允许不受信任的程序检索当前用户的密码(这将是有史以来最大的安全漏洞)。
所以,在我的想法中,你只剩下一个选择。让您的用户再次输入密码,结果输入应转换为SecureString
此示例是I have seen here
的字符串类的扩展方法using System.Security;
// ...
public static SecureString ConvertToSecureString(this string password)
{
if (password == null)
throw new ArgumentNullException("password");
unsafe
{
fixed (char* passwordChars = password)
{
var securePassword = new SecureString(passwordChars, password.Length);
securePassword.MakeReadOnly();
return securePassword;
}
}
}
您可以使用它来转换用户输入的密码并启动流程
using(frmGetPassword fgp = new frmGetPassword())
{
if(DialogResult.OK == fgp.ShowDialog())
{
SecureString ss = fgp.Password.ConvertToSecureString();
var processInfo = new ProcessStartInfo
{
WorkingDirectory = workingDirectory,
FileName = "a name",
UserName = loggedUserName,
Password = ss,
Domain = userNameDomain,
UseShellExecute = false,
};
Process.Start(processInfo);
}
}
答案 1 :(得分:1)
我使用Windows密码存储来管理此类密码。查看包含Windows API的http://credentialmanagement.codeplex.com/库。您的Setup-Routine或Admin可以将密码添加到商店,然后可以在运行时从应用程序中检索该密码。唯一的缺点是商店是用户特定的。您无法创建可在多个用户中使用的密码。
就这么简单:
_credentials = new CredentialSet("myApp:*");
if (_credentials.Count == 0)
{
//TODO: ask user for password, supply it here, or use windows UI to set password (rundll32.exe keymgr.dll, KRShowKeyMgr)
var c = new Credential()
{
Target = "myApp:Production",
Username = "SomeUser",
Description = "Credentials for doing something...",
PersistanceType = PersistanceType.LocalComputer,
Type = CredentialType.DomainPassword
};
c.Save();
_credentials.Add(c);
}