CAPTCHAと2FAを実装
This commit is contained in:
@@ -67,6 +67,43 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2段階認証設定 -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="bi bi-shield-lock me-2"></i>2段階認証(2FA)</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{if .totpError}}<div class="alert alert-danger">{{.totpError}}</div>{{end}}
|
||||
{{if .totpSuccess}}<div class="alert alert-success">{{.totpSuccess}}</div>{{end}}
|
||||
{{if .user.TOTPEnabled}}
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<span class="badge bg-success me-2"><i class="bi bi-check-lg me-1"></i>有効</span>
|
||||
<span class="text-muted">2段階認証が有効になっています</span>
|
||||
</div>
|
||||
<form method="POST" action="/profile/totp/disable">
|
||||
{{.csrfField}}
|
||||
<div class="mb-3">
|
||||
<label for="totp_disable_password" class="form-label">現在のパスワードを入力して無効化</label>
|
||||
<input type="password" class="form-control" id="totp_disable_password" name="password"
|
||||
placeholder="パスワード" required style="max-width:320px">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-danger">
|
||||
<i class="bi bi-shield-x me-1"></i>2段階認証を無効化
|
||||
</button>
|
||||
</form>
|
||||
{{else}}
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<span class="badge bg-secondary me-2"><i class="bi bi-x-lg me-1"></i>無効</span>
|
||||
<span class="text-muted">2段階認証が設定されていません</span>
|
||||
</div>
|
||||
<p class="text-muted small">2段階認証を有効にするとセキュリティが向上します。Google Authenticator などのアプリが必要です。</p>
|
||||
<a href="/profile/totp/setup" class="btn btn-primary">
|
||||
<i class="bi bi-shield-plus me-1"></i>2段階認証を設定する
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 通知設定 -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
|
||||
83
web/templates/pages/totp_setup.html
Normal file
83
web/templates/pages/totp_setup.html
Normal file
@@ -0,0 +1,83 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-7 col-lg-6">
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="bi bi-shield-lock me-2"></i>2段階認証の設定</h5>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
{{if .error}}
|
||||
<div class="alert alert-danger">{{.error}}</div>
|
||||
{{end}}
|
||||
|
||||
<div class="alert alert-info">
|
||||
<i class="bi bi-info-circle me-1"></i>
|
||||
Google Authenticator、Authy などの認証アプリを使用してください。
|
||||
</div>
|
||||
|
||||
<h6 class="fw-bold mb-3">手順</h6>
|
||||
<ol class="mb-4">
|
||||
<li class="mb-2">認証アプリを開き、新しいアカウントを追加してください。</li>
|
||||
<li class="mb-2">下のQRコードをスキャンするか、シークレットキーを手動で入力してください。</li>
|
||||
<li class="mb-2">アプリに表示された6桁のコードを下の欄に入力して確認してください。</li>
|
||||
</ol>
|
||||
|
||||
<div class="text-center mb-4">
|
||||
<img src="data:image/png;base64,{{.qrCode}}" alt="QRコード" class="border rounded"
|
||||
style="max-width:200px">
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold">シークレットキー(手動入力の場合)</label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control font-monospace" id="secretKey" value="{{.secret}}"
|
||||
readonly>
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="copySecret()" title="コピー">
|
||||
<i class="bi bi-clipboard"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-text">認証アプリで「手動入力」を選択し、このキーを入力してください。</div>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="/profile/totp/setup">
|
||||
{{.csrfField}}
|
||||
<div class="mb-3">
|
||||
<label for="totp_password" class="form-label fw-bold">現在のパスワード</label>
|
||||
<input type="password" class="form-control" id="totp_password" name="password"
|
||||
placeholder="パスワードを入力" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="totp_code" class="form-label fw-bold">認証コードで確認</label>
|
||||
<input type="text" class="form-control form-control-lg text-center" id="totp_code"
|
||||
name="totp_code" placeholder="000000" maxlength="6" pattern="[0-9]{6}" inputmode="numeric"
|
||||
autocomplete="off" autofocus required>
|
||||
<div class="form-text">認証アプリに表示された6桁のコードを入力してください。</div>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-shield-check me-1"></i>有効化
|
||||
</button>
|
||||
<a href="/profile" class="btn btn-outline-secondary">キャンセル</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "scripts"}}
|
||||
<script>
|
||||
function copySecret() {
|
||||
const el = document.getElementById('secretKey');
|
||||
el.select();
|
||||
navigator.clipboard.writeText(el.value).then(() => {
|
||||
const btn = el.nextElementSibling;
|
||||
btn.innerHTML = '<i class="bi bi-check-lg"></i>';
|
||||
setTimeout(() => { btn.innerHTML = '<i class="bi bi-clipboard"></i>'; }, 2000);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user