diff --git a/admin-web/src/views/AdminAccounts.vue b/admin-web/src/views/AdminAccounts.vue index 3fe2021..65b9297 100644 --- a/admin-web/src/views/AdminAccounts.vue +++ b/admin-web/src/views/AdminAccounts.vue @@ -28,7 +28,7 @@ async function load() { } async function createAccount() { - if (form.password.length < 12) return message.error('初始密码至少 12 位') + if (form.password.length < 6 || form.password.length > 128) return message.error('初始密码必须为 6 到 128 位') await api.createAdminAccount(form) message.success('管理员已创建') createOpen.value = false @@ -50,7 +50,9 @@ async function update(account: Account, patch: Partial) { } async function submitReset() { - if (!resetTarget.value || resetPassword.value.length < 12) return message.error('新密码至少 12 位') + if (!resetTarget.value || resetPassword.value.length < 6 || resetPassword.value.length > 128) { + return message.error('新密码必须为 6 到 128 位') + } await api.resetAdminPassword(resetTarget.value.id, resetPassword.value) message.success('密码已重置,现有会话已撤销') resetTarget.value = null @@ -110,7 +112,7 @@ onMounted(load) - + operator @@ -123,7 +125,7 @@ onMounted(load) - + diff --git a/admin-web/src/views/ChangePassword.vue b/admin-web/src/views/ChangePassword.vue index 27a14e8..8fb2851 100644 --- a/admin-web/src/views/ChangePassword.vue +++ b/admin-web/src/views/ChangePassword.vue @@ -11,8 +11,8 @@ const loading = ref(false) async function submit() { if (loading.value) return if (!form.currentPassword) return message.error('请输入当前密码') - if (form.newPassword.length < 12 || form.newPassword.length > 128) { - return message.error('新密码长度必须为 12 到 128 位') + if (form.newPassword.length < 6 || form.newPassword.length > 128) { + return message.error('新密码长度必须为 6 到 128 位') } if (form.newPassword !== form.confirmPassword) return message.error('两次输入的新密码不一致') loading.value = true @@ -43,12 +43,13 @@ async function logout() { - + diff --git a/backend/MiaoJiZhang.Api.Tests/ApiIntegrationTests.cs b/backend/MiaoJiZhang.Api.Tests/ApiIntegrationTests.cs index a4e978c..7d1ef14 100644 --- a/backend/MiaoJiZhang.Api.Tests/ApiIntegrationTests.cs +++ b/backend/MiaoJiZhang.Api.Tests/ApiIntegrationTests.cs @@ -664,8 +664,12 @@ public sealed class ApiIntegrationTests(ApiFixture fixture) using var superAdmin = await fixture.AdminAsync(); var suffix = Guid.NewGuid().ToString("N")[..10]; var username = $"viewer_{suffix}"; - const string initialPassword = "viewer-initial-password-123"; - const string permanentPassword = "viewer-permanent-password-456"; + const string initialPassword = "init06"; + const string permanentPassword = "new006"; + var shortPasswordResponse = await superAdmin.PostAsJsonAsync( + "/api/admin/security/accounts", + new { username = $"{username}_short", password = "12345", role = "viewer" }); + Assert.Equal(HttpStatusCode.BadRequest, shortPasswordResponse.StatusCode); var createdResponse = await superAdmin.PostAsJsonAsync( "/api/admin/security/accounts", new { username, password = initialPassword, role = "viewer" }); diff --git a/backend/MiaoJiZhang.Api/Controllers/AdminAccountsController.cs b/backend/MiaoJiZhang.Api/Controllers/AdminAccountsController.cs index 7fdb9d9..4b6c351 100644 --- a/backend/MiaoJiZhang.Api/Controllers/AdminAccountsController.cs +++ b/backend/MiaoJiZhang.Api/Controllers/AdminAccountsController.cs @@ -37,7 +37,8 @@ public sealed class AdminAccountsController(AppDbContext db) : ControllerBase public async Task Create(CreateAdminUserRequest request, CancellationToken ct) { var username = request.Username.Trim(); - if (username.Length is < 3 or > 64 || request.Password.Length is < 12 or > 128 || + if (username.Length is < 3 or > 64 || + request.Password.Length is < AdminPasswordPolicy.MinLength or > AdminPasswordPolicy.MaxLength || !AdminRoles.All.Contains(request.Role)) return BadRequest(new ApiError("ADMIN_ACCOUNT_INVALID", "管理员账号、密码或角色无效")); if (await db.AdminUsers.AnyAsync(item => item.Username == username, ct)) @@ -90,8 +91,8 @@ public sealed class AdminAccountsController(AppDbContext db) : ControllerBase ResetAdminPasswordRequest request, CancellationToken ct) { - if (request.Password.Length is < 12 or > 128) - return BadRequest(new ApiError("ADMIN_PASSWORD_INVALID", "密码长度必须为 12 到 128 位")); + if (request.Password.Length is < AdminPasswordPolicy.MinLength or > AdminPasswordPolicy.MaxLength) + return BadRequest(new ApiError("ADMIN_PASSWORD_INVALID", "密码长度必须为 6 到 128 位")); var user = await db.AdminUsers.FindAsync([id], ct); if (user is null) return NotFound(); user.PasswordHash = AdminSessionService.HashPassword(request.Password); diff --git a/backend/MiaoJiZhang.Api/Controllers/AdminAuthController.cs b/backend/MiaoJiZhang.Api/Controllers/AdminAuthController.cs index 64fc5c4..604e561 100644 --- a/backend/MiaoJiZhang.Api/Controllers/AdminAuthController.cs +++ b/backend/MiaoJiZhang.Api/Controllers/AdminAuthController.cs @@ -53,8 +53,9 @@ public sealed class AdminAuthController( AdminChangePasswordRequest request, CancellationToken ct) { - if (request.NewPassword.Length < 12 || request.NewPassword.Length > 128) - return BadRequest(new ApiError("ADMIN_PASSWORD_INVALID", "新密码长度必须为 12 到 128 位")); + if (request.NewPassword.Length < AdminPasswordPolicy.MinLength || + request.NewPassword.Length > AdminPasswordPolicy.MaxLength) + return BadRequest(new ApiError("ADMIN_PASSWORD_INVALID", "新密码长度必须为 6 到 128 位")); var principal = AdminRequestContext.Principal(HttpContext)!; var user = await db.AdminUsers.FirstAsync(item => item.Id == principal.UserId, ct); if (!BCrypt.Net.BCrypt.Verify(request.CurrentPassword, user.PasswordHash)) diff --git a/backend/MiaoJiZhang.Api/Services/AdminBootstrapService.cs b/backend/MiaoJiZhang.Api/Services/AdminBootstrapService.cs index 9dacb06..fe5e774 100644 --- a/backend/MiaoJiZhang.Api/Services/AdminBootstrapService.cs +++ b/backend/MiaoJiZhang.Api/Services/AdminBootstrapService.cs @@ -15,10 +15,10 @@ public sealed class AdminBootstrapService( var username = configuration["Admin:BootstrapUsername"]?.Trim(); var password = configuration["Admin:BootstrapPassword"]; if (string.IsNullOrWhiteSpace(username) || username.Length is < 3 or > 64 || - string.IsNullOrWhiteSpace(password) || password.Length < 12) + string.IsNullOrWhiteSpace(password) || password.Length < AdminPasswordPolicy.MinLength) { throw new InvalidOperationException( - "首次启动必须通过 Admin__BootstrapUsername 和 Admin__BootstrapPassword 配置管理员,密码至少 12 位"); + "首次启动必须通过 Admin__BootstrapUsername 和 Admin__BootstrapPassword 配置管理员,密码至少 6 位"); } var now = DateTime.UtcNow; diff --git a/backend/MiaoJiZhang.Api/Services/AdminPasswordPolicy.cs b/backend/MiaoJiZhang.Api/Services/AdminPasswordPolicy.cs new file mode 100644 index 0000000..03abaf6 --- /dev/null +++ b/backend/MiaoJiZhang.Api/Services/AdminPasswordPolicy.cs @@ -0,0 +1,7 @@ +namespace MiaoJiZhang.Api.Services; + +public static class AdminPasswordPolicy +{ + public const int MinLength = 6; + public const int MaxLength = 128; +}