【c#】Blazor を使用してパスワードの生成をしてみる【SPA】
実際のページはこちら
パスワードの生成ツールを作成してみました。
文字数や生成個数を設定でき、数字、大文字、記号の設定が可能です。
記号は自分で使用する文字の記載が可能で、似通った文字は除外し、除外する文字の設定も可能です。
クライアント側で使用する文字を入力するのは、想定外の文字が入力されて不具合が起きるなど、セキュリティ面も気になりますが、Blazor WebAssenbly を使用し、クライアント側で処理が完結するため、大丈夫なんじゃないかと思っています。
Index.razor の html 部分
@page "/"
@inject IJSRuntime JSRuntime
@using System.Text
@using System.Text.RegularExpressions
<PageTitle>パスワードの生成</PageTitle>
<h1>パスワードの生成</h1>
<hr />
<div class="row">
<div class="col-auto">
<div class="input-group mb-3">
<div class="input-group-text">文字数</div>
<input type="number" min="3" max="20" class="form-control" @bind="length">
</div>
<div class="input-group">
<div class="input-group-text">生成数</div>
<input type="number" min="3" max="100" class="form-control" @bind="quantity">
</div>
</div>
<div class="col-auto">
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" @bind="useDigits">
数字を使用する
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" @bind="useUppercaseLetters">
大文字を使用する
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" @bind="useSymbols">
記号 <input type="text" @bind="symbols" class="form-control form-control-sm w-auto d-inline-block" /> を使用する
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" @bind="excludeSimilarCharacters">
似通った文字 <input type="text" @bind="excludeCharacters" class="form-control form-control-sm w-auto d-inline-block" /> を除外する
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" @bind="displayVertical">
結果を縦に表示
</label>
</div>
</div>
</div>
<button class="btn btn-primary mt-4" @onclick="GetPasswords">作成</button>
<button class="btn btn-primary mt-4" @onclick="CopyText">コピー</button>
<hr />
<div style="font-family:monospace;" id="copy">
@((MarkupString)result)
</div>
Index.razor のコード部分
@code {
private bool useDigits = true;
private bool useUppercaseLetters = true;
private bool useSymbols = false;
private string symbols = "!@#$%^&*-+={[}]?";
private bool excludeSimilarCharacters = true;
private string excludeCharacters = "louv10DIOQUV";
private int length = 10;
private int quantity= 10;
private bool displayVertical = true;
private string result = "ここに結果が表示されます。";
private async Task CopyText()
{
await JSRuntime.InvokeVoidAsync("copyText");
}
protected override async Task OnInitializedAsync()
{
GetPasswords();
}
private void GetPasswords()
{
if (displayVertical == false)
{
result = "<table><tr><td class='pe-3'>";
}
else
{
result = "";
}
var passwordList = new List<string>();
for (var i = 0; i < quantity; i++)
{
passwordList.Add(GeneratePassword());
}
result += String.Join(displayVertical ? "<br>" : "<td class='pe-3'>", passwordList);
if (displayVertical == false)
{
result += "</tr></table>";
}
}
private string GeneratePassword()
{
string characters = "abcdefghijklmnopqrstuvwxyz";
if (useDigits) characters += "1234567890";
if (useUppercaseLetters) characters += "ABCDEFGHIJKLMNOPQRLSTUVWXYZ";
if (useSymbols) characters += symbols.Trim();
if (excludeSimilarCharacters)
{
foreach(char c in excludeCharacters.Trim().ToCharArray())
{
characters = characters.Replace(c.ToString(), "");
}
}
StringBuilder passwordBuilder = new StringBuilder();
Random random = new Random();
while (true)
{
for (int i = 0; i < length; i++)
{
int position = random.Next(characters.Length);
char c = characters[position];
passwordBuilder.Append(c);
}
if (
Regex.IsMatch(passwordBuilder.ToString(), "[a-z]")
&& (useDigits == false || Regex.IsMatch(passwordBuilder.ToString(), "[0-9]"))
&& (useUppercaseLetters == false || Regex.IsMatch(passwordBuilder.ToString(), "[A-Z]"))
&& (useSymbols == false || Regex.IsMatch(passwordBuilder.ToString(), "[!@#$%^&*-+={[}]?]"))
)
{
return passwordBuilder.ToString();
}
else
{
passwordBuilder.Clear();
}
}
}
}
index.html ページの変更
javascript は blazor では.razor ページ上には直接書けないようなので、wwwroot の index.html の body の閉じタグの前に以下を追加する。
生成したテキストをコピーする javascript
<script>
function copyText() {
var target = document.getElementById("copy");
document.getSelection().selectAllChildren(target);
document.execCommand("copy");
document.getSelection().empty();
alert("コピーしました。");
}
</script>
感想
今回はコピー機能を使用するため部分的に javascript を使用しましたが、それ以外ではフロントエンド側でも c#で完結できるのはすっきりしていて良いと思いました。