feat(admin): 修改密码功能(PBKDF2原密码校验 + 新密码≥8位合规 + 页面 + 导航入口)
- AdminUserService.changePassword: verify旧密码 + 新密码≥8位且≠原密码 + hash更新 - AdminController: GET/POST /admin/password(当前登录用户,Sa-Token loginId) - password.ftl: 表单 + 前端JS预校验(长度/一致/新旧不同) - _macros.ftl: 侧边栏footer加修改密码入口 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -22,4 +22,16 @@ public interface AdminUserService {
|
||||
* 应用启动时确保存在至少一个管理员(表空则按 app.yml imutil.admin 初始化)
|
||||
*/
|
||||
void ensureDefaultAdmin();
|
||||
|
||||
/**
|
||||
* 修改当前登录用户密码
|
||||
* <p>
|
||||
* 校验原密码(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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user