次のシナリオがあります。
PasswordBox
)そして、私はすでにこれを読んでいます MVVMのPasswordBoxに関する質問
しかし、その方法については答えがありません! 「決してそんなことはしない」だけではありません。
パスワードを渡す正しい方法は何ですか?セキュリティの問題を解決する方法は?
Binding
からPasswordBox
への適切な方法はなく、パスワードはどこかに保存されません。
それで、そのようなことをするMVVMの方法は何ですか?
パターンが壊れていても、そのようなことを達成するための良い方法はありますか?
それを取得するためのFunc<string>
の考えですが、Bindingがないと、これは混乱します...
Update(うまくいけば暗号化された)パスワードストアからPasswordBoxを初期化する場合も同じです。それはMVVMパターンを壊していませんか?ユーザーは、アプリケーションを起動するたびにパスワードを入力したり、私が信じているデータベースで作業したりすることを望んでいません。
個人的には、PasswordBox
コントロール全体をLoginCommandに渡すだけです。
ViewModelレイヤーがView固有のオブジェクトを参照するようになったので、MVVMが壊れることはわかっていますが、この特定のケースでは問題ないと思います。
したがって、次のようなXAMLを使用している可能性があります。
<Button Content="Login"
Command="{Binding LoginCommand}"
CommandParameter="{Binding ElementName=MyPasswordBox}" />
そして、次のようなことを行うLoginCommand
:
private void Login(object obj)
{
PasswordBox pwBox = obj as PasswordBox;
SomeBlackBoxClass.ValidatePassword(UserName, pwBox.Password);
}
値に対して何らかの暗号化アルゴリズムを実行し、その値のハッシュをユーザーのパスワードのハッシュと比較することもできると思います
private void Login(object obj)
{
PasswordBox pwBox = obj as PasswordBox;
var encryptedPassword = SomeLibrary.EncryptValue(pwBox.Password, someKey);
if (encryptedPassword == User.EncryptedPassword)
// Success
}
私はPasswordBox
コントロールやセキュリティの専門家ではありませんが、ユーザーのパスワードをプレーンテキストでアプリケーション内のメモリのどこにも保存したくないことは知っています。
(技術的には、プレーンテキストとしてPasswordBox.Password
に保存されます-必要に応じて Snoop のようなものを使用してこれを確認できます-ただし、通常、PasswordBoxはユーザーが必要とする時間より長く存在しませんログインするために、実際の「パスワード」はユーザーが入力したテキストであり、正しい場合と正しくない場合があります。キーロガーが同じ情報を取得する可能性があります。)
バインドできるSecureString依存関係プロパティを公開するUserControlを作成することで、この問題を解決しました。このメソッドは、パスワードを常にSecureStringに保持し、MVVMを「破壊」しません。
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
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;
};
}
}
コントロールの使用は非常に簡単です。コントロールのパスワードDependencyPropertyをViewModelのPasswordプロパティにバインドするだけです。 ViewModelのPasswordプロパティはSecureStringである必要があります。
<controls:PasswordUserControl Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
バインディングのModeおよびUpdateSourceトリガーを最適なものに変更します。
プレーンテキストのパスワードが必要な場合は、次のページでSecureStringと文字列を変換する適切な方法について説明します。 http://blogs.msdn.com/b/fpintos/archive/2009/06/12/how -to-properly-convert-securestring-to-string.aspx 。もちろん、プレーンテキストの文字列を保存するべきではありません...
mvvmの理解に応じて(私の方法では、コードビハインドが許可される場合があります)
だから私はPasswordBoxと名前付きTextBlockを作成します
XAML
<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" />
コードビハインド
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;
}
あなたがあなたのパスワードが保存されているのを見ることができるようにそしてあなたはそれに簡単にバインドすることができます
その記事はさておき、この特定の質問に関連する他の投稿がいくつかあります。添付プロパティを使用してバインディングを実現できます。参照してください: