Reactでパスワード強度検出器を実装する方法

Reactでパスワード強度検出器を実装する方法

序文

パスワード強度ファイル検証ツール。アカウントを登録するときに、ユーザーの現在のパスワード強度を評価する必要があります。このプロセスでは、検出器を作成する必要があります。製品がルールを変更しやすいように、柔軟に記述するのが最適です。

まずは効果を見てみましょう~~ 以下はスクリーンショットに対応するステータスです

使用

1 パラメータの受け渡し

const PasswordForce = passwordForce({ inputValue, className: 'password-force', });

2 使用

<PasswordForce.View />

3 検証

文字PasswordForce.invaildWordを超えていないか確認する

実装例

antd を設定して、プロンプターをパスワード入力ボックスにバインドしましょう。

1 と 2 は変更する必要はありませんが、実際には入力の値を監視して値を設定する必要があります。そこで、値の変更を監視する関数を定義することができます。

const [入力値、設定入力値] = useState('');
    const passwordChange = (値: 文字列) => {
    入力値を設定します。
};
定数 onPasswordInput = (e: 任意) => {
    パスワード変更(e?.target?.value || '');
};

後はバインドするだけです。バインド後は正常に表示できます。ただし、不正な文字が入力された場合は、インターセプターを介してインターセプトする必要があります。

<フォーム.アイテム
...
ルール={[
    {
      必須: true、
      メッセージ: 'パスワードが空ではありません'、
    },
    ({ getFieldValue }) => ({
      バリデータ(_, 値) {
        パスワード変更(値);
        (PasswordForce.invaildWord) の場合 {
          Promise.reject() を返します。
            新しいエラー('パスワードに無効な文字が含まれています。'),
          );
        }
        Promise.resolve() を返します。
      },
    })、
]}
...

さて、スライスの使用が終わったので、実装してみましょう。

コンポーネントの記述

コンポーネントの記述

輸入 {
  ルールマッチ結果を取得、
  IpasswordForce、
  IpasswordRule、
  isMatchForceResultConfig、
  マッチ結果構成、
  パスワードブレークキー、
} '@/utils/passwordStrengthChecker' から;
React をインポートし、{ CSSProperties } を 'react' から取得します。
'react' から useEffect をインポートします。
'react' から useState をインポートします。
'styled-components' から styled をインポートします。

インターフェースプロパティ{
  入力値: 文字列;
  色?: 文字列;
  スタイル?: CSSProperties;
  クラス名?: 文字列;
  カスタムルール?: IpasswordRule[];
}
列挙型フォースマップ{
  high = '高'、
  真ん中 = '真ん中'、
  low = '低い'、
}
const boolNumSum = (リスト: ブール値[]) =>
  list.reduce<数値>(
    (前の値、現在の値) =>
      現在の値? 前の値 + 1 : 前の値、
    0,
  );

const passwordForce: (props: props) => {
  表示: React.FC;
  呼び出された単語: ブール値;
  強制: IpasswordForce;
} = ({ inputValue, style = {}, className, customRule = [] }) => {
  const [force, setforce] = useState<IpasswordForce>(false);
  const [無効な単語、setIsInvaildWord] = useState(false);
  const inputValueLen = inputValue?.length || 0;
  定数setData = () => {
    強制を設定します(false);
    定数isFirstWordUp = inputValue[0] === inputValue[0].toLocaleUpperCase();
    const ruleRsult = getRuleMatchResult(customRule, 入力値, 未定義, '');
    const matchNum = boolNumSum(ruleRsult.list.map((e) => e[passwordBreakKey]));
    定数matchResultConfig: matchResultConfig[] = [
      { 最小: 0、最大: 32、一致数: 1、値: 'low' },
      { 最小: 7、最大: 32、一致数: 2、値: '中央' },
      { 最小: 7、最大: 32、一致数: 3、値: '中央' },
      { 最小: 15、最大: 32、matchNum: 3、値: 'high'、必要: isFirstWordUp },
    ];
    setIsInvaildWord(ruleRsult.invaildWord);
    matchResultConfig.forEach((config) => {
      isMatchForceResultConfig(config、matchNum、inputValueLen) &&
        setforce(config.value);
    });
  };
  使用効果(() => {
    入力値? setData(): setforce(false);
  }, [入力値]);
  戻る {
    表示: () =>
      力 ? (
        <PasswordForceWrap {...{ スタイル、クラス名 }}>
          {ForceMap[力]}
        </PasswordForceWrap>
      ) : (
        <></>
      )、
    無効な単語、
    力、
  };
};
デフォルトの passwordForce をエクスポートします。

const PasswordForceWrap = styled.span`
  色: ${({ color }) => 色 ?? '#000'};
`;

データ構造分析

  • リスト ルールのコレクション。各ルールには一致とルール名、およびルール データ自体が含まれます。
  • マップは、ルールに対応するデータを直接取得するのに便利な方法です。
  • matchCountは一致した文字の数です
  • invaildWord は、不正な文字 (ルール自体で指定された文字を超える文字) があるかどうかを判断するために使用できます。

プロセス分析

これは実際には2つのプロセスです

  • 入力値とルールに従って処理されたデータが得られ、得られたデータ構造は上図のようになります。
  • 次に、ビジネスニーズを満たす構成データを記述し、isMatchForceResultConfig関数に渡して設定強度を一致させます。

えーと。 ビジネス コードについては以上です。 依存関係は、基本的に変更されないコードです。以下の基礎ファイルに基づいて、ビジネス コードで非常に複雑なバリデーターを構成し、この部分のコードを他のファイルに実装できます。

基礎コードの分析

チャットしましょう。

以下は、任意のフレームワークを実行できる純粋な ts コードです。

パスワード強度チェッカー.ts

'./constants' から { numberList、specialList、wordList } をインポートします。

タイプマップ = <U, T>(オプション: {
  配列: U[];
  範囲: 数値;
  マッチリスト: T[];
  tokenMap: (updateItem: T、トークン: U、インデックス: 数値) => T;
  breakKey?: 文字列;
  arrayMap?: (項目: U、インデックス: 数値) => void;
}) => T[];

/**
 * 配列を一致させて設定する
 */
エクスポートconst setArrayMatch: map = ({
  配列、
  範囲、
  マッチリスト、
  ブレークキー、
  トークンマップ、
  配列マップ、
}) => {
  const tokenLen = 配列の長さ;
  (tokenIndex = tokenLen - 1; tokenIndex >= 0; tokenIndex--) の場合 {
    const 配列トークン = 配列[トークンインデックス];
    配列マップ && 配列マップ(配列トークン、トークンインデックス);
    (findIndex = range - 1; findIndex >= 0; findIndex--) {
      matchList = matchList.map((item) =>
        トークンマップ(アイテム、配列トークン、検索インデックス)、
      );
    }
    if (breakKey && !matchList.map((e) => (e as any)[breakKey]).includes(false))
      壊す;
  }
  matchList を返します。
};

エクスポート const passwordBreakKey = 'isMatch';
エクスポートタイプ IpasswordRule = {
  リスト: 文字列[];
  isMatch: ブール値;
  名前: 文字列;
};
エクスポートconst defaultPasswordRuleList = [
  { 名前: 'special'、リスト: specialList },
  { 名前: 'num'、リスト: numberList },
  { 名前: '単語'、リスト: 単語リスト },
];

PickValue<T, K は keyof T> = T[K] を拡張します。

エクスポートconst getRuleMatchResult: (
  カスタムルール: IpasswordRule[],
  入力値: 文字列、
  デフォルトルールを無効にする?: ブール値、
  breakKey?: 文字列、
) => {
  リスト: IpasswordRule[];
  マップ: Map<PickValue<IpasswordRule, 'name'>, boolean>;
  一致カウント: 数値;
  呼び出された単語: ブール値;
} = (カスタムルール、入力値、disableDefaultRule = true、breakKey) => {
  ルールリスト = [
    ...(disableDefaultRule ? defaultPasswordRuleList : []),
    ...カスタムルール、
  ].map((item) => ({ ...item, [passwordBreakKey]: false }));
  const 範囲 = Math.max(...ruleList.map((ruleItem) => ruleItem.list.length));
  matchCount = 0 とします。
  ルールリスト = setArrayMatch<文字列、IpasswordRule>({
    配列: inputValue.split(''),
    範囲、
    マッチリスト: ルールリスト、
    // breakKey 完全一致ではない
    breakKey: breakKey === void 0 ? passwordBreakKey : breakKey,
    トークンマップ: (ルールアイテム、入力トークン、検索インデックス) => {
      const match = ルール項目?.list[findIndex] === 入力トークン;
      (一致)の場合{
        マッチカウント++;
        戻り値 { ...ruleItem, isMatch: true };
      }
      ルールアイテムを返します。
    },
  });
  戻る {
    リスト: ルールリスト、
    マップ: 新しいマップ(ruleList.map((e) => [e.name, e[passwordBreakKey]])),
    一致数、
    // この値を取得するには、breakkey を null 文字列に設定する必要があります。早期に終了すると、条件が早期に終了します。// この値を取得するには、breakkey を null 文字列に設定する必要があります
    無効な単語: matchCount !== inputValue.length、
  };
};

エクスポートconst isMatchForceResultConfig = (
  設定: matchResultConfig、
  matchNum: 数値、
  入力値の長さ: 数値、
) => {
  戻る (
    マッチ番号 === config.matchNum &&
    入力値の長さ >= config.min &&
    入力値の長さ <= config.max &&
    (config.need !== 未定義 ? config.need : true)
  );
};

エクスポートタイプmatchResultConfig = {
  min: 数値;
  最大: 数;
  matchNum: 数値;
  値: IpasswordForce;
  必要か?: ブール値;
  戻る?: IpasswordForce;
};
エクスポート タイプ IpasswordForce = false | 'high' | 'middle' | 'low';

このプロセスでは、ルールをマージします。1 つはデフォルト ルール、もう 1 つはカスタム ルールです。ルールをカスタマイズすると、デフォルト ルールが上書きされます。
ルールの中から、ルール数が最も長いものを探します。これは、後でトラバースするときにすべてのルールをマージできるためです。ルールがいくつあっても、トラバースの回数はあまり変わりません。

トラバーサル関数は、内部ロジックをカスタマイズできる独立した高階関数です。このとき、対応するルールを一致させ、対応するルールのプロパティをアクティブにして、一致した文字を蓄積します。

最後に、すべての一致に達したら、トラバーサルを終了する必要があります。ただし、トラバーサルを終了できない状況が 1 つあります。それは、不正な文字があるかどうかを判断する必要がある場合です。

最後に、この関数は処理されたデータを上位コンポーネントにスローします。これがプロセスです。

データスローの過程で、いくつかのシナリオではルールに対応するデータの特別な処理が必要になる場合がありますが、配列構造の場合は非常に不便です。そのため、スローされたデータはリスト型とマップ型に分ける必要があります。上位アプリケーションが対応するルールを取得したい場合は、map.get(ルール名)を操作できます。

定数.ts

エクスポート const specialList = ["~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "-", "/", ",", ".", "?", "<", ">", ";", ":", "[", "]", "{", "}", "|", "\\"];
エクスポート const numberList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
export const wordList = ["q", "a", "z", "w", "s", "x", "e", "d", "c", "r", "f", "v", "t", "g", "b", "y", "h", "n", "u", "j", "m", "i", "k", "o", "l", "p", "Q", "A", "Z", "W", "S", "X", "E", "D", "C", "R", "F", "V", "T", "G", "B", "Y", "H", "N", "U", "J", "M", "I", "K", "O", "L", "P"];

他の

コード検出器がそんなに複雑である必要があるのか​​と疑問に思う人も多いでしょう。正規表現を使用する方がよいのではないでしょうか。実際、実用的な観点から見ると、正規表現の方が便利ですが、時にはルールに従いたくない、手動コーディングのスリルを味わいたい、退屈なコードからより多くの遊び心を得たいなど、非常に複雑に見えますが、基礎となるレイヤーをカプセル化し、柔軟性を保持し、ビジネスレイヤーで可能な限りシンプルに保つコードを書きます。実際に試してみることは不可能ではありませんが、レビュー中に批判されることもあります。コピーするときは注意してください。時間が足りない場合やコーディングスキルが低い場合は、このコードを使用することはお勧めしません。問題が発生しても責任を負いません。

要約する

これで、React でパスワード強度検出器を実装する方法に関するこの記事は終了です。React パスワード強度検出器の関連コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、次の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

<<:  Raspberry Pi 4b ubuntu19 サーバーへの docker-ce のインストール手順

>>:  MySQL でよく使われる型変換関数の概要 (推奨)

推薦する

Vite2+Vue3を使用してMarkdownドキュメントをレンダリングする練習

目次カスタム Vite プラグインvite-plugin-markdownの使用Front Matt...

Vueカスタム命令の詳細な説明

目次Vueカスタムディレクティブカスタムディレクティブフック機能出力関連属性アプリケーション例要約す...

Ubuntu 18.04 は mysql 5.7.23 をインストールします

以前、Ubuntu 16.04 に MySQL をスムーズにインストールしました。今回、Ubuntu...

ランダムな文字を生成する Java サンプルコード

サンプルコード: java.util.Random をインポートします。 java.util.UUI...

クラウド サーバーを使用して CentOS システムに .NET 6.0 をインストールする

.NET SDK ダウンロード リンクhttps://dotnet.microsoft.com/do...

MySQL初心者はグループ化や集計クエリの煩わしさから解放されます

目次1. グループクエリの概略図2. groupbyキーワード構文の詳細な説明3. 簡単なグループク...

MySQL データベースの Binlog 使用法の概要 (必読)

MySQL データベースにとって binlog バイナリ ログがどれほど重要であるかについては詳し...

Vue の高度な構築プロパティの詳細な説明

目次1. ディレクティブカスタムディレクティブ2. ミックスイン3. 継承を拡張する4. 提供して注...

Tomcatのクラスロードメカニズムを説明する記事

目次- 序文 - - JVM クラスローダー - 1. JVMクラスローダー2. クラスローダーのソ...

ウェブサイト開発におけるフロントエンド開発者とアーティストの知識の違い

概要: 多くの企業、特にインターネット Web サイトを主な事業とする企業のほとんどが、「アーティス...

HTML のタイトル、段落、改行、水平線、特殊文字についての簡単な説明

タイトルXML/HTML コードコンテンツをクリップボードにコピー< h1 >第 1 レ...

Vue.js プロジェクトの開始方法

目次1. Node.jsとVue 2. ローカル開発環境でフロントエンドのVueプロジェクトを実行す...

MySQLでバッチを更新するいくつかの方法

通常、フィールド値を更新するには次の SQL ステートメントを使用します。 mytable を更新し...

Linux オペレーティング システムでよく使用される MySQL コマンドの概要

以下に、一般的な MySQL コマンドをいくつか示します。 -- データベース サービスを開始します...

iPhone デバイスの WAP ページでフォントサイズが大きい問題の解決策

JavaScriptコントロールを使用したくない場合は、次の方法を試してください。 Safariブラ...