首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将SecureString放入PasswordBox

将SecureString放入PasswordBox
EN

Stack Overflow用户
提问于 2013-11-02 21:40:29
回答 2查看 2.1K关注 0票数 10

我有一个现有的SecureString,我想把它放到一个PasswordBox 中,而不透露.Password。这能办到吗?例如:

代码语言:javascript
复制
tbPassword.SecurePassword = DecryptString(Properties.Settings.Default.proxyPassword);

在本例中,DecryptString生成一个SecureString。但是,SecurePassword是一个只读属性,所以我不能给它赋值。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-03 01:25:42

你不能这么做。

但是,您可以做的是将占位符文本放在它的位置(它甚至可以是"placeholder",我们只是使用它来在方框中显示几个点)。

放入占位符后,当您在程序中的某个地方检索“当前密码”时,首先检查自输入占位符密码以来PasswordChanged事件是否已经触发。如果事件尚未触发,请使用旧的存储密码,如果事件已触发,则使用PasswordBox属性中的当前密码。

票数 10
EN

Stack Overflow用户

发布于 2021-04-02 10:53:30

不好意思,晚加,但这可能是一个想法的人,谁也走进这个。(至少我在2021年在这页上找到了它)

看看PasswordBox的来源,我们可以看到它的属性是如何实现的。密码属性设置器只将字符串复制到一个临时SecureString中,并将其转发到其内部存储。readonly SecurePassword属性返回内部SecureString的副本,因此对其调用.Clear() / .AppendChar(char)只会更改此副本,如果没有对其调用.MakeReadonly()。

代码语言:javascript
复制
[TemplatePart(Name = "PART_ContentHost", Type = typeof (FrameworkElement))]
public sealed class PasswordBox : Control, ITextBoxViewHost
{
  public SecureString SecurePassword => this.TextContainer.GetPasswordCopy();
  [DefaultValue("")]
  [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  public unsafe string Password
  {
    [SecurityCritical] get { /* left out to reduce space */ }
    [SecurityCritical] set
    {
      if (value == null)
        value = string.Empty;
      // We want to replicate this, but copy a SecureString instead of creating one from a String
      using (SecureString secureString = new SecureString())
      {
        for (int index = 0; index < value.Length; ++index)
          secureString.AppendChar(value[index]);
        this.SetSecurePassword(secureString);
      }
    }
  }
}

这可能有点麻烦,但是调用私有SetSecurePassword可能最接近绕过转换到明文以便使用密码设置器:(我们制作一个临时副本,就像在.Password setter中一样,因为我们不负责管理提供的SecureString的生存期,甚至可以只读)

代码语言:javascript
复制
// option 1: streight reflection 
var setPasswordMethod = typeof(PasswordBox).GetMethod("SetSecurePassword", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] {typeof(SecureString)}, null);
using (var copy = mySecurePassword.Copy())
    setPasswordMethod.Invoke(PasswordControl, new[] {copy});

// option 2: compiled delegate so reflection will only kick in once
Action<PasswordBox, SecureString> setSecurePassword = null; // this would be a cache lookup instead of a local variable.
if (setSecurePassword == null)
{
    var passwordBox = Expression.Parameter(typeof(PasswordBox), "passwordBox");
    var password = Expression.Parameter(typeof(SecureString), "securePassword");
    //// if we want to include code for making the temporary copy in the delegate, use this instead to create its body
    //var passwordCopy = Expression.Variable(typeof(SecureString));
    //var makePasswordCopy = Expression.Call(password, nameof(SecureString.Copy), Type.EmptyTypes);
    //var body = Expression.Block(new[] {passwordCopy},
    //    Expression.Assign(passwordCopy, makePasswordCopy),
    //    Expression.TryFinally(
    //        Expression.Call(passwordBox, "SetSecurePassword", Type.EmptyTypes, passwordCopy),
    //        Expression.Call(Expression.Convert(passwordCopy, typeof(IDisposable)),
    //            nameof(IDisposable.Dispose), Type.EmptyTypes)));
    var body = Expression.Call(passwordBox, "SetSecurePassword", Type.EmptyTypes, password);
    setSecurePassword = Expression.Lambda<Action<PasswordBox, SecureString>>(body, passwordBox, password).Compile();
}
using (var copy = mySecurePassword.Copy()) // if we would make the copy inside the delegate, we won't need to do it here.
    setSecurePassword(PasswordControl, copy);

我希望这对任何人都有帮助。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19747195

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档