diff --git a/backend/controllers/security.go b/backend/controllers/security.go index df2a98a..3737f4b 100644 --- a/backend/controllers/security.go +++ b/backend/controllers/security.go @@ -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, "请先登录") diff --git a/backend/controllers/user_security.go b/backend/controllers/user_security.go index 81cc3eb..1575cc3 100644 --- a/backend/controllers/user_security.go +++ b/backend/controllers/user_security.go @@ -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 { diff --git a/backend/models/security_credentials.go b/backend/models/security_credentials.go index c973f9a..1b1340c 100644 --- a/backend/models/security_credentials.go +++ b/backend/models/security_credentials.go @@ -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:"-"` diff --git a/backend/services/credentials/service.go b/backend/services/credentials/service.go index 6d513f3..4741ecf 100644 --- a/backend/services/credentials/service.go +++ b/backend/services/credentials/service.go @@ -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) } diff --git a/frontend/src/views/components/RecoverySetupPrompt/RecoverySetupPrompt.vue b/frontend/src/views/components/RecoverySetupPrompt/RecoverySetupPrompt.vue index ffcf7a2..0975fef 100644 --- a/frontend/src/views/components/RecoverySetupPrompt/RecoverySetupPrompt.vue +++ b/frontend/src/views/components/RecoverySetupPrompt/RecoverySetupPrompt.vue @@ -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 { diff --git a/frontend/src/views/components/SecuritySettings/SecuritySettings.js b/frontend/src/views/components/SecuritySettings/SecuritySettings.js index 45d26fa..f02968d 100644 --- a/frontend/src/views/components/SecuritySettings/SecuritySettings.js +++ b/frontend/src/views/components/SecuritySettings/SecuritySettings.js @@ -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 || '离线恢复码生成失败') diff --git a/frontend/src/views/components/UserManagement/RecoveryCodeDialog/RecoveryCodeDialog.vue b/frontend/src/views/components/UserManagement/RecoveryCodeDialog/RecoveryCodeDialog.vue index 3a4e09e..f747f8e 100644 --- a/frontend/src/views/components/UserManagement/RecoveryCodeDialog/RecoveryCodeDialog.vue +++ b/frontend/src/views/components/UserManagement/RecoveryCodeDialog/RecoveryCodeDialog.vue @@ -23,8 +23,8 @@