C# 密码框和 MVVM
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15390727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PasswordBox and MVVM
提问by Mare Infinitus
We have the following scenario:
我们有以下场景:
- MVVM userinterface where a user can place his password (actually a
PasswordBox
) - Server that shall do some work
- Server connects to some Database that requires authentification
- MVVM 用户界面,用户可以在其中放置密码(实际上是一个
PasswordBox
) - 应该做一些工作的服务器
- 服务器连接到一些需要身份验证的数据库
And I already read this Question on PasswordBox in MVVM
我已经在 MVVM 中阅读了关于 PasswordBox 的这个问题
But there is no answer on how to do! Just lots over "never ever do that".
但是没有关于如何做的答案!只是很多“永远不要那样做”。
What is the correct way of passing a password around? How to resolve the security issues?
传递密码的正确方法是什么?如何解决安全问题?
There is no proper way of Binding
to the PasswordBox
and
the Password shall not be stored somewhere, okay.
有没有适当的方式Binding
向PasswordBox
和密码不得保存在某个地方,好不好。
So, what is the MVVM way of doing such things?
那么,什么是 MVVM 做这些事情的方式呢?
Even if the pattern is broken, is there a good way to achieve such things?
即使模式被打破,有没有什么好的方法可以实现这样的事情?
Thought of a Func<string>
to retrieve it, but without Binding this
will get a mess...
想Func<string>
找回它,但没有绑定这会变得一团糟......
UpdateSame for initialising the PasswordBox from a (hopefully encrypted) password store. Isn't that breaking the MVVM pattern? The User does not want to enter the password each time he starts the application or wants to work with the database I believe.
更新相同用于从(希望加密的)密码存储初始化 PasswordBox。这不是打破了 MVVM 模式吗?用户不想在每次启动应用程序或想要使用我相信的数据库时都输入密码。
采纳答案by Rachel
Personally I just pass the entire PasswordBox
control to my LoginCommand
我个人只是将整个PasswordBox
控制权传递给我的 LoginCommand
I know it breaks MVVM because the ViewModel layer now references a View-specific object, but I think in this specific case it's OK.
我知道它破坏了 MVVM,因为 ViewModel 层现在引用了一个特定于视图的对象,但我认为在这种特定情况下它没问题。
So I might have XAML that looks like this:
所以我可能有如下所示的 XAML:
<Button Content="Login"
Command="{Binding LoginCommand}"
CommandParameter="{Binding ElementName=MyPasswordBox}" />
And a LoginCommand
that does something like this:
和 aLoginCommand
做这样的事情:
private void Login(object obj)
{
PasswordBox pwBox = obj as PasswordBox;
SomeBlackBoxClass.ValidatePassword(UserName, pwBox.Password);
}
I suppose you could also run some kind of encryption algorithm on the value and compare the hash of that value to the hash of the user's password too
我想您还可以对该值运行某种加密算法,并将该值的哈希值与用户密码的哈希值进行比较
private void Login(object obj)
{
PasswordBox pwBox = obj as PasswordBox;
var encryptedPassword = SomeLibrary.EncryptValue(pwBox.Password, someKey);
if (encryptedPassword == User.EncryptedPassword)
// Success
}
I'm no expert on the PasswordBox
control or security, but I do know that you don't want to be storing the user's password in plain text anywhere in memory within your application
我不是PasswordBox
控制或安全方面的专家,但我知道您不希望将用户密码以纯文本形式存储在应用程序内存中的任何位置
(Technically, it's stored as plain text in PasswordBox.Password
- you can use something like Snoopto verify this if you want - however typically the PasswordBox doesn't exist for longer than it takes the user to login, and the actual "password" is just text entered by the user, which may or may not be correct. A keylogger could get you the same information.)
(从技术上讲,它以纯文本形式存储在PasswordBox.Password
- 如果需要,您可以使用Snoop 之类的东西来验证这一点 - 但是通常 PasswordBox 的存在时间不会超过用户登录所需的时间,而实际的“密码”只是文本由用户输入,这可能正确也可能不正确。键盘记录器可以为您提供相同的信息。)
回答by Chandramouleswaran Ravichandra
Leaving that article aside - there are a few other posts related to this particular question. You can achieve binding using attached properties. Please see:
把那篇文章放在一边——还有一些其他的帖子与这个特定的问题相关。您可以使用附加属性实现绑定。请参见:
- I believe this question is a duplicate of PasswordBox Binding
- The above post points to - http://www.wpftutorial.net/PasswordBox.html
- 我相信这个问题是PasswordBox Binding的重复
- 上面的帖子指向 - http://www.wpftutorial.net/PasswordBox.html
回答by WiiMaxx
depending on your understanding of mvvm (in my way code behind is allowed in some cases)
取决于您对 mvvm 的理解(以我的方式,在某些情况下允许隐藏代码)
so i create a PasswordBox and also a named TextBlock
所以我创建了一个 PasswordBox 和一个命名的 TextBlock
Xaml
xml
<PasswordBox Height="23" Width="156" PasswordChar="*" PasswordChanged="pwBoxUser_PasswordChanged"/>
<TextBlock Height="1" Width="1" Name="MD5pw" Text="{Binding Passwort, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}" VerticalAlignment="Top" />
codebehind
代码隐藏
private void pwBoxUser_PasswordChanged(object sender, RoutedEventArgs e)
{
var pBox =sender as PasswordBox;
string blank=pBox.Password;
//to crypt my blank Password
var sMD5 = myMD5.toMD5(blank); //implement your crypt logic here
blank ="";
MD5pw.Text = sMD5;
}
like you can see your password is save and you can easy bind to it
就像您可以看到您的密码已保存,您可以轻松绑定到它
回答by DinoM
I have solved this problem by creating a UserControl that exposes a SecureString dependency property that can be bound to. This method keeps the password in a SecureString at all times, and doesn't "break" MVVM.
我已经通过创建一个 UserControl 来解决这个问题,它公开了一个可以绑定到的 SecureString 依赖项属性。此方法始终将密码保存在 SecureString 中,并且不会“破坏” MVVM。
UserControl
用户控件
XAML
XAML
<UserControl x:Class="Example.PasswordUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<PasswordBox Name="PasswordBox" />
</Grid>
</UserControl>
CS
CS
public partial class PasswordUserControl : UserControl
{
public SecureString Password
{
get { return (SecureString) GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(SecureString), typeof(UserCredentialsInputControl),
new PropertyMetadata(default(SecureString)));
public PasswordUserControl()
{
InitializeComponent();
// Update DependencyProperty whenever the password changes
PasswordBox.PasswordChanged += (sender, args) => {
Password = ((PasswordBox) sender).SecurePassword;
};
}
}
Example usage
示例用法
Using the control is very straightforward, just bind the password DependencyProperty on the control to a Password property on your ViewModel. The ViewModel's Password property should be a SecureString.
使用该控件非常简单,只需将控件上的密码 DependencyProperty 绑定到 ViewModel 上的 Password 属性即可。ViewModel 的 Password 属性应该是 SecureString。
<controls:PasswordUserControl Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
Change the Mode and UpdateSource trigger on the binding to whatever is best for you.
将绑定上的 Mode 和 UpdateSource 触发器更改为最适合您的触发器。
If you need the password in plain text, the following page describes the proper way to convert between SecureString and string: http://blogs.msdn.com/b/fpintos/archive/2009/06/12/how-to-properly-convert-securestring-to-string.aspx. Of course you shouldn't store the plain text string...
如果您需要纯文本密码,以下页面介绍了 SecureString 和字符串之间的正确转换方法:http: //blogs.msdn.com/b/fpintos/archive/2009/06/12/how-to-properly -convert-securestring-to-string.aspx。当然你不应该存储纯文本字符串......