This commit is contained in:
parent
0a81d70ba3
commit
cea2269249
@ -300,7 +300,7 @@ func SetSecurityQuestion(ctx *context.Context, w http.ResponseWriter, req *http.
|
||||
response.NewSuccessResponse(map[string]any{"configured": true}).FPrint(w)
|
||||
}
|
||||
|
||||
// GenerateRecoveryCodes 生成一组只显示一次的离线恢复码。
|
||||
// GenerateRecoveryCodes 生成一组离线恢复码,未使用的有效恢复码可在安全验证后再次查看。
|
||||
func GenerateRecoveryCodes(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
if ctx == nil || ctx.UserID <= 0 {
|
||||
writeSecurityError(w, response.NeedLogin, "请先登录")
|
||||
|
||||
@ -140,7 +140,7 @@ func RevealManagedRecoveryCodes(ctx *context.Context, w http.ResponseWriter, req
|
||||
response.NewSuccessResponse(map[string]any{"user_id": target.ID, "codes": codes, "revealed": true}).FPrint(w)
|
||||
}
|
||||
|
||||
// GenerateManagedRecoveryCodes 为目标用户生成只显示一次的安全码。
|
||||
// GenerateManagedRecoveryCodes 为目标用户生成安全码,有管理权限的管理员可在安全验证后再次查看有效安全码。
|
||||
func GenerateManagedRecoveryCodes(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
var input managedUserSecurityRequest
|
||||
if err := decodeUserRequest(w, req, &input); err != nil {
|
||||
|
||||
@ -15,7 +15,8 @@ type SecurityQuestion struct {
|
||||
|
||||
func (SecurityQuestion) TableName() string { return "security_question" }
|
||||
|
||||
// RecoveryCode 保存一次性离线恢复码的 Argon2id 哈希,UsedAt 非空表示已经消费或撤销。
|
||||
// RecoveryCode 保存一次性离线恢复码的 Argon2id 哈希和用于安全验证后查看的密文。
|
||||
// UsedAt 非空表示已经消费或撤销,此时密文会被清除,不再允许查看或使用。
|
||||
type RecoveryCode struct {
|
||||
ID int `xorm:"id bigint unsigned not null pk autoincr" json:"-"`
|
||||
UserID int `xorm:"user_id bigint not null index" json:"-"`
|
||||
|
||||
@ -143,7 +143,7 @@ func (s *Service) VerifySecurityQuestion(userID int, answer string) (bool, error
|
||||
return password.Check(item.AnswerHash, answer)
|
||||
}
|
||||
|
||||
// GenerateRecoveryCodes 撤销旧码并生成一组只返回一次的离线恢复码。
|
||||
// GenerateRecoveryCodes 撤销旧码并生成一组离线恢复码,保存哈希和受保护的密文以支持安全验证后再次查看。
|
||||
func (s *Service) GenerateRecoveryCodes(userID int, count int) ([]string, error) {
|
||||
return s.GenerateRecoveryCodesContext(context.Background(), userID, count)
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ const generateRecoveryCodes = async () => {
|
||||
generatedCodes.value = response.data.codes
|
||||
globalStatus.userInfos.recoveryCodesConfigured = true
|
||||
globalStatus.userInfos.showRecoverySetupPrompt = false
|
||||
ElMessage.success("恢复码已生成,请仅保存这一次显示的内容")
|
||||
ElMessage.success("恢复码已生成,请妥善保存;可在安全设置中验证本人密码后再次查看有效恢复码")
|
||||
} catch (error) {
|
||||
ElMessage.error(error?.message || "离线恢复码生成失败,请稍后重试")
|
||||
} finally {
|
||||
|
||||
@ -258,7 +258,7 @@ export function usePage() {
|
||||
scheduleRecoveryCodeHide()
|
||||
recoveryConfigured.value = true
|
||||
await globalStatus.refresh()
|
||||
notify('恢复码已生成,请仅保存这一次显示的内容', 'success')
|
||||
notify('恢复码已生成,请妥善保存;验证本人密码后可再次查看有效恢复码', 'success')
|
||||
} catch (error) {
|
||||
if (isRecentAuthenticationCancelled(error) || !isRecoveryViewCurrent(version)) return
|
||||
if (error !== 'cancel' && error !== 'close') notify(error?.message || '离线恢复码生成失败')
|
||||
|
||||
@ -23,8 +23,8 @@
|
||||
|
||||
<div v-if="codes.length" class="recovery-code-result">
|
||||
<div v-if="!revealed" class="result-title">
|
||||
<strong>新安全码仅显示这一次</strong>
|
||||
<span>请立即交给用户妥善保存,关闭弹窗后无法再次查看。</span>
|
||||
<strong>新安全码已生成</strong>
|
||||
<span>请交给用户妥善保存。60 秒后自动隐藏,验证当前管理员密码后可再次查看有效安全码。</span>
|
||||
</div>
|
||||
<div v-else class="result-title">
|
||||
<strong>当前有效安全码</strong>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user