From 707f0b48248e827b32cf75c164eacb91602b9b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BF=9E=E9=BE=99=E5=88=9A?= Date: Thu, 9 Jul 2026 14:00:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(admin):=20=E4=BF=AE=E6=94=B9=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E5=8A=9F=E8=83=BD=EF=BC=88PBKDF2=E5=8E=9F=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E6=A0=A1=E9=AA=8C=20+=20=E6=96=B0=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E2=89=A58=E4=BD=8D=E5=90=88=E8=A7=84=20+=20=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=20+=20=E5=AF=BC=E8=88=AA=E5=85=A5=E5=8F=A3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AdminUserService.changePassword: verify旧密码 + 新密码≥8位且≠原密码 + hash更新 - AdminController: GET/POST /admin/password(当前登录用户,Sa-Token loginId) - password.ftl: 表单 + 前端JS预校验(长度/一致/新旧不同) - _macros.ftl: 侧边栏footer加修改密码入口 Co-Authored-By: Claude --- .../imutil/controller/AdminController.java | 33 +++++++++++++++ .../com/imutil/service/AdminUserService.java | 12 ++++++ .../service/impl/AdminUserServiceImpl.java | 23 +++++++++++ src/main/resources/templates/_macros.ftl | 1 + src/main/resources/templates/password.ftl | 41 +++++++++++++++++++ 5 files changed, 110 insertions(+) create mode 100644 src/main/resources/templates/password.ftl diff --git a/src/main/java/com/imutil/controller/AdminController.java b/src/main/java/com/imutil/controller/AdminController.java index 431b75f..e826196 100644 --- a/src/main/java/com/imutil/controller/AdminController.java +++ b/src/main/java/com/imutil/controller/AdminController.java @@ -116,6 +116,39 @@ public class AdminController { ctx.redirect(basePath + "/admin/login"); } + // ==================== 修改密码 ==================== + + @Get + @Mapping("/password") + public Object passwordPage(@Param(defaultValue = "") String msg) { + ModelAndView mv = view("password.ftl", "修改密码", "password"); + mv.put("msg", msg); + return mv; + } + + @Post + @Mapping("/password") + public void changePassword(@Param(defaultValue = "") String oldPassword, + @Param(defaultValue = "") String newPassword, + @Param(defaultValue = "") String confirmPassword, + Context ctx) throws Throwable { + // 两次新密码一致性前端已校验,后端兜底 + if (!newPassword.equals(confirmPassword)) { + ctx.redirect(basePath + "/admin/password?msg=pwdconfirm"); + return; + } + try { + // 当前登录用户ID(Sa-Token 登录时存的是 AdminUser.id) + adminUserService.changePassword(StpUtil.getLoginIdAsLong(), oldPassword, newPassword); + log.info("管理员密码已修改 loginId={}", StpUtil.getLoginIdAsLong()); + ctx.redirect(basePath + "/admin/password?msg=pwddone"); + } catch (Exception e) { + // 原密码错误 / 新密码不合规统一提示,细节见日志 + log.warn("修改密码失败 : {}", e.getMessage()); + ctx.redirect(basePath + "/admin/password?msg=pwdfail"); + } + } + // ==================== 首页(仪表盘) ==================== @Get diff --git a/src/main/java/com/imutil/service/AdminUserService.java b/src/main/java/com/imutil/service/AdminUserService.java index 5f7c517..6e65d93 100644 --- a/src/main/java/com/imutil/service/AdminUserService.java +++ b/src/main/java/com/imutil/service/AdminUserService.java @@ -22,4 +22,16 @@ public interface AdminUserService { * 应用启动时确保存在至少一个管理员(表空则按 app.yml imutil.admin 初始化) */ void ensureDefaultAdmin(); + + /** + * 修改当前登录用户密码 + *

+ * 校验原密码(PBKDF2 verify)+ 新密码合规(≥ 8 位且与原密码不同)后写新 hash。 + * + * @param userId 用户ID + * @param oldPassword 原密码(明文) + * @param newPassword 新密码(明文,需 ≥ 8 位且与原密码不同) + * @throws com.imutil.common.BizException 原密码错误 / 新密码不合规 / 用户不存在 + */ + void changePassword(Long userId, String oldPassword, String newPassword); } diff --git a/src/main/java/com/imutil/service/impl/AdminUserServiceImpl.java b/src/main/java/com/imutil/service/impl/AdminUserServiceImpl.java index fcbe454..6d756b4 100644 --- a/src/main/java/com/imutil/service/impl/AdminUserServiceImpl.java +++ b/src/main/java/com/imutil/service/impl/AdminUserServiceImpl.java @@ -1,6 +1,7 @@ package com.imutil.service.impl; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.imutil.common.BizException; import com.imutil.common.PasswordUtil; import com.imutil.entity.AdminUser; import com.imutil.mapper.AdminUserMapper; @@ -74,4 +75,26 @@ public class AdminUserServiceImpl implements AdminUserService { adminUserMapper.insert(u); log.info("已初始化默认管理员账号: {}(请尽快修改默认密码)", defaultUsername); } + + @Override + public void changePassword(Long userId, String oldPassword, String newPassword) { + AdminUser u = adminUserMapper.selectById(userId); + if (u == null) { + throw new BizException("用户不存在"); + } + // 原密码校验(PBKDF2 常量时间比对) + if (!PasswordUtil.verify(oldPassword, u.getPasswordHash())) { + throw new BizException("原密码错误"); + } + // 新密码合规:≥ 8 位且与原密码不同(防改成又一个弱密码) + if (newPassword == null || newPassword.length() < 8) { + throw new BizException("新密码至少 8 位"); + } + if (newPassword.equals(oldPassword)) { + throw new BizException("新密码不能与原密码相同"); + } + u.setPasswordHash(PasswordUtil.hash(newPassword)); + adminUserMapper.updateById(u); + log.info("管理员密码已修改 userId={} username={}", userId, u.getUsername()); + } } diff --git a/src/main/resources/templates/_macros.ftl b/src/main/resources/templates/_macros.ftl index f4882eb..2373a87 100644 --- a/src/main/resources/templates/_macros.ftl +++ b/src/main/resources/templates/_macros.ftl @@ -70,6 +70,7 @@ 数据迁移

diff --git a/src/main/resources/templates/password.ftl b/src/main/resources/templates/password.ftl new file mode 100644 index 0000000..88e3d1d --- /dev/null +++ b/src/main/resources/templates/password.ftl @@ -0,0 +1,41 @@ +<#-- + 修改密码页 + 校验:原密码正确 + 新密码 ≥ 8 位 + 新旧不同 + 两次新密码一致(前端 JS + 后端 AdminUserServiceImpl 兜底) +--> +<#import "_macros.ftl" as m> +<@m.layout active="password" title="修改密码"> + <#if msg?has_content> +
+ <#if msg=='pwddone'>✅ 密码修改成功,下次登录请使用新密码 + <#elseif msg=='pwdfail'>❌ 修改失败:原密码错误,或新密码不合规(至少 8 位且与原密码不同) + <#elseif msg=='pwdconfirm'>❌ 两次输入的新密码不一致 + +
+ + +
+

当前默认密码为弱密码(admin123),建议尽快修改为含字母+数字的强密码。

+
+ +
+ +
+
+
+ + +