19

次のシナリオがあります。

  1. ユーザーが自分のパスワードを配置できるMVVMユーザーインターフェイス(実際にはPasswordBox
  2. いくつかの作業を行うサーバー
  3. サーバーは、認証が必要なデータベースに接続します

そして、私はすでにMVVMのPasswordBoxでこの質問を読みました

しかし、その方法についての答えはありません!「決してそんなことはしない」だけではありません。

パスワードを渡す正しい方法は何ですか?セキュリティの問題を解決する方法は?

Bindingへの適切な方法はなくPasswordBox、パスワードはどこかに保存されません。

それで、そのようなことをするMVVMの方法は何ですか?

パターンが壊れていても、そのようなことを達成するための良い方法はありますか?

Func<string>それを取得することを考えましたが、バインドしないと、これは混乱します...

(うまくいけば暗号化された)パスワードストアからPasswordBoxを初期化するためにSameを更新します。それはMVVMパターンを壊していませんか?ユーザーは、アプリケーションを起動するたびにパスワードを入力したり、私が信じているデータベースを操作したりすることを望んでいません。

4

5 に答える 5

39

個人的には、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制御やセキュリティの専門家ではありませんが、ユーザーのパスワードをアプリケーション内のメモリのどこかにプレーンテキストで保存したくないことは知っています。

(技術的には、プレーンテキストとして保存されます-必要に応じてSnoopPasswordBox.Passwordのようなものを使用してこれを確認できます-ただし、通常、PasswordBoxはユーザーがログインするのにかかる時間より長く存在せず、実際の「パスワード」は単なるテキストですユーザーが入力したもので、正しい場合と正しくない場合があります。キーロガーが同じ情報を取得する可能性があります。)

于 2013-03-13T16:41:40.630 に答える
7

バインドできるSecureString依存関係プロパティを公開するUserControlを作成することで、この問題を解決しました。このメソッドは、パスワードを常にSecureStringに保持し、MVVMを「破壊」しません。

UserControl

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。もちろん、プレーンテキストの文字列を保存するべきではありません...

于 2015-11-23T23:32:53.900 に答える
1

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;
    }

あなたがあなたのパスワードが保存されているのを見ることができるようにそしてあなたはそれに簡単にバインドすることができます

于 2013-03-20T10:03:10.153 に答える
0

その記事はさておき、この特定の質問に関連する他の投稿がいくつかあります。アタッチされたプロパティを使用してバインディングを実現できます。参照してください:

  1. この質問は PasswordBoxバインディングの複製だと思います
  2. 上記の投稿は-http://www.wpftutorial.net/PasswordBox.htmlを指しています
于 2013-03-13T16:25:55.643 に答える
0

上記のDinoMによって提案されたIMOソリューションは、上記のChandramouleswaran Ravichandraによって提供された両方のリンクで使用されている「Passwordhelper」クラスよりもエレガントなソリューションであり、はるかに理解しやすいものです(ただし、ブログhttp:/ /blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html

'UserCredentialsInputControl'タイプがないために、DinoMのソリューションを機能させることができなかった場合は、このパラメーターをtypeof(PasswordUserControl)に変更するだけで機能します。

SingletonSeanのYoutubeチャンネルに次のタイトルのビデオがあります。

PasswordBox(MVVM)へのバインド-EASY WPF(.NET CORE)https://www.youtube.com/watch?v=G9niOcc5ssw

これは、PasswordPropertyの基本タイプにSecureStringの代わりにstringを使用していることを除いて、完全な例であるという点で私が見つけた最高のソースですが、簡単に修正できます。彼はまた、GitHubリポジトリでビデオのソースコードへのリンクを提供しています。

于 2021-01-23T14:40:31.200 に答える