Nuxtでパスワード作成サービスを作ってみる

掲載日

はじめに

仕事柄、そこまで厳重でなくていい適当なパスワードを作成することが多く、オンラインツールを使っていたのですが微妙に希望通りの仕様のものが無いので、パスワード作成サービスを自作してみました。

作っていく

必須要件

  • ファーストビューに適当な設定のパスワードが表示される。
  • 作成されたパスワードをクリックで自動的にクリップボードにコピーされる。
    (この二点が個人的に重要で、細かいことですがスクロールの手間を減らしたかった。)
  • javascriptで完結
    (作成の度に通信が発生しないこと。)
  • セキュリティはそんなに気にしなくて良い。
    それっぽい設定をデフォルトとする(8文字くらい、英数字と必要に応じて記号を組み合わせて作成できる。)
  • 組織ごとにアカウントを割り振り、初期パスワードを設定することがあるので個数を指定できること。

できたもの

出来上がったもののGitHubソースがこちらにあります。

API等は使っていないので、パンくずコンポーネント(AtomBreadcrumb )を削除すればNuxt環境ならコピペでそのまま動かせると思います。
(レイアウトはtailwind CSSを使用しているので、ライブラリが入ってない場合レイアウト崩れは起きますが利用には問題ないはず。)

解説

パスワード作成時に重複文字をはじく

肝心のランダム生成部分はこちらの記事を参考もといほぼコピペにしております。
解説も上記記事の方が丁寧かつ分かりやすいと思うので割愛。

応用として、「同じ文字は含めない」機能を追加しているのでその方法の解説を載せておきます。
このサービスはランダム変数を使っているので、(確率的にほぼありえないと思いますが)同じ文字が連続した(「aaaaaa」みたいな)パスワードが生成されることがあるので、そういったことを防ぐために使えるオプション機能です。

サンプルコードが以下になります。

duplicateChecker = []; // 重複チェック用配列
password = ""; // パスワード作成用変数
passCount = 0; // パスワードの文字数チェック用変数
size = 8; // パスワードの文字数
string = "abcdefghijklmnopqrstuvwxyz" // パスワードに使用する文字列
while (true) { // 重複を弾きたいのでfor文ではなくwhile文で回す
  passChar = string.charAt(Math.floor(Math.random() * string.length)); // ランダムにパスワードに使用する文字を決定
  if (duplicateChecker.includes(passChar)) { // 重複チェック用配列にすでに入っている文字なら
    continue; // 以下の処理をせず次へ
  }
  // 重複チェック配列にない文字なら
  duplicateChecker.push(passChar);
 // チェック配列に追加
  password += passChar; // パスワードに文字列を使用する
  passCount++; // 文字数カウントをインクリメント
  if (passCount == size) { // 指定サイズ揃ったらループを抜ける
    break;
  }
}
console.log(password) // -> 重複のないパスワードが出力される。

連続した文字が多いとセキュリティ的にちょっと…ということで追加してる機能ですが、規則性のある文字列(「123456」「abcdef」のような連続した数字・文字列とか、「password」みたいな意味のある単語とか)が生成されるのも防ぎたいので、ここはいい方法思いつき次第更新していきたいです。

また、パスワード自体がランダムだと辞書攻撃には比較的強いとは思いますが、今どきはパスワードそのもの以外のセキュリティ(二段階認証とか、パスワードの受付をN秒に1回に制限するとか)が重要だったりするのであまり要らない機能かなという気もしてます。

紛らわしい文字を除く

自分の場合、作成したパスワードは大抵人に渡すことになるので、なるべく「0(数字のゼロ)」と「O(英大文字のオー)」のような紛らわしい文字は除きたくて付けた機能です。

とはいえやることはシンプルで、紛らわしい文字列の配列定数を作って起き、パスワードに使用する文字列の後に3行ほど追加するだけです。

const excludeMistakePattern = ["O", "0"];
 // 紛らわしい文字列の定数

string = "ABCDEFGHIJKLMNO012345678" // パスワードに使用する文字列
for (const mistakeWord of excludeMistakePattern) {
  string = string.replace(mistakeWord, ""); // 紛らわしい文字列を空文字に置換
}
console.log(string) // -> ABCDEFGHIJKLMN12345678

パスワードクリックで全選択+クリップボードにコピー

ここも大事なところで、都度「Ctrl+A」→「Ctrl+V」でパスワードをコピペするのは嫌なので、クリックで勝手にコピーして欲しいのでクリックで自動でコピーするようになっています。

以前はクリップボードにコピーする場合、document.execCommandというメソッドを使用していましたが、今は非推奨になっているためnavigator.clipboardメソッドを使用します。
詳細はMDNにて詳しく記載されています。

const onClickPassword = (event: Event) => {
  if (!event) {
    return;
  }

  if (!event.target) {
    return;
  }

  const target = event.target as HTMLInputElement;
  target.select(); // 全選択
  // コピー
  navigator.clipboard.writeText(copyStr).then(
  	() => {
		console.log("成功した時の処理")
  	},
  	() => {
   		console.log("失敗した時の処理")
  	}
  );

};

// クリックでコピーしたいinputタグに@click="onClickPassword"追記

おわりに

このくらいのツールであればNuxtで小一時間ほどで作れるので、Nuxtの勉強をしつつブログのコンテンツ強化にもなり楽しかったです。
実務ではここからbasic認証の設定をしたりするので、htaccess、htpasswdジェネレーターみたいなものも作っていきたいです。

参考サイト

記事の作成者のA.W.のアイコン

この記事を書いた人

A.W.
茨城県在住Webエンジニアです。 PHPなどを業務で使用しています。 趣味ではGoやNuxt、Flutterをやってます。

Comment