diff --git a/src/main/java/com/budwk/app/sys/controller/SysLoginController.java b/src/main/java/com/budwk/app/sys/controller/SysLoginController.java index 4ea9dada..b3acd906 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysLoginController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysLoginController.java @@ -1,6 +1,5 @@ package com.budwk.app.sys.controller; -import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.codec.Base64Encoder; import cn.hutool.core.convert.Convert; @@ -69,14 +68,49 @@ public class SysLoginController { @ApiOperation("用户本地登录页面") @Filters public String login(HttpServletRequest req, HttpSession session) { - return "beetl:/platform/sys/login.html"; + return localLoginOrCas(req, session); } @At @Ok("re") @Filters - public String h5() { - return "beetl:/platform/sys/login.html"; + public String h5(HttpServletRequest req, HttpSession session) { + return localLoginOrCas(req, session); + } + + /** + * 本地登录页入口处理。 + * 参数说明: + * 1. req:当前登录页请求,用于读取请求地址、查询参数以及 CAS 回调后的登录跳转参数。 + * 2. session:当前会话,用于读取 CAS 客户端写入的认证断言。 + * 返回值为 Nutz re 视图字符串:未开启 SSO 或已通过 CAS 认证时返回本地登录页,开启 SSO 且未认证时返回 CAS 登录重定向地址。 + */ + private String localLoginOrCas(HttpServletRequest req, HttpSession session) { + if (!conf.getBoolean("cas.enable", false)) { + return "beetl:/platform/sys/login.html"; + } + + Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION); + if (assertion != null && assertion.getPrincipal() != null) { + // CAS 已认证只代表允许访问本地登录页,不在这里自动完成系统登录,避免访问 /platform/login 时被带到首页。 + return "beetl:/platform/sys/login.html"; + } + + return ">>:" + buildCasLoginUrl(req); + } + + /** + * 构建 CAS 登录地址。 + * 参数说明: + * 1. req:当前请求,用于把原始访问地址作为 redirect 参数带回系统。 + * 返回值为完整 CAS 登录 URL,CAS 认证成功后会回调到 cas.client-call-back-url。 + */ + private String buildCasLoginUrl(HttpServletRequest req) { + String requestURI = req.getRequestURI(); + String query = req.getQueryString(); + String redirect = StrUtil.isNotBlank(query) ? requestURI + "?" + query : requestURI; + String callBackUrl = conf.get("cas.client-host-url") + conf.get("cas.client-call-back-url") + "?redirect=" + URLEncoder.encode(redirect, StandardCharsets.UTF_8); + return conf.get("cas.server-login-url") + "?service=" + URLEncoder.encode(callBackUrl, StandardCharsets.UTF_8); } diff --git a/src/main/java/com/budwk/app/sys/controller/SysUserController.java b/src/main/java/com/budwk/app/sys/controller/SysUserController.java index 607a58c2..d10bd5b0 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysUserController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysUserController.java @@ -17,10 +17,12 @@ import com.budwk.app.sys.services.SysUnitService; import com.budwk.app.sys.services.SysUserService; import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.web.commons.base.Globals; +import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Chain; import org.nutz.dao.Cnd; import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.Lang; @@ -150,6 +152,21 @@ public class SysUserController { } } + @At("/resetAllPwd") + @Ok("json") + @SaCheckPermission("sys.manager.user.edit") + @Aop(TransAop.READ_COMMITTED) + @SLog(tag = "重置所有用户密码", msg = "排除superadmin后批量重置用户密码") + public Object resetAllPwd() { + try { + // 批量重置只返回影响人数,避免把所有用户的新密码暴露到页面或日志中。 + int count = sysUserService.resetAllUserPwdExcludeSuperadmin(); + return Result.success().addData(count); + } catch (Exception e) { + return Result.error(); + } + } + @At("/delete/?") @Ok("json") @SaCheckPermission("sys.manager.user.delete") diff --git a/src/main/java/com/budwk/app/sys/services/SysUserService.java b/src/main/java/com/budwk/app/sys/services/SysUserService.java index 29e6fdc2..1a683dd7 100644 --- a/src/main/java/com/budwk/app/sys/services/SysUserService.java +++ b/src/main/java/com/budwk/app/sys/services/SysUserService.java @@ -78,6 +78,14 @@ public interface SysUserService extends BaseService { */ void deleteByIds(String[] userIds); + /** + * 重置所有普通用户密码,系统内置 superadmin 账号不参与重置。 + * 返回值为本次实际完成密码重置的用户数量,便于前端提示管理员操作影响范围。 + * + * @return 已重置密码的用户数量 + */ + int resetAllUserPwdExcludeSuperadmin(); + /** * 通过用户ID和菜单父ID获取下级权限菜单 * diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java index d6a97a61..11174da2 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java @@ -29,6 +29,7 @@ import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.Lang; import org.nutz.lang.Strings; +import org.nutz.lang.random.R; import org.nutz.plugins.wkcache.annotation.CacheDefaults; import org.nutz.plugins.wkcache.annotation.CacheRemove; import org.nutz.plugins.wkcache.annotation.CacheRemoveAll; @@ -220,6 +221,26 @@ public class SysUserServiceImpl extends BaseServiceImpl implements Sys dao().clear("sys_user", Cnd.where("id", "in", userIds)); } + /** + * 批量重置普通用户密码。 + * 业务边界:superadmin 为系统内置管理员账号,必须保持原密码不被批量操作影响。 + * + * @return 实际重置密码的用户数量 + */ + @Override + @Aop(TransAop.READ_COMMITTED) + public int resetAllUserPwdExcludeSuperadmin() { + List users = this.query(Cnd.where("loginname", "!=", "superadmin")); + for (Sys_user user : users) { + String pwd = PwdUtil.generate(12); + String salt = R.UU32(); + String encryptPwd = PwdUtil.getPassword(pwd, salt); + this.update(Chain.make("password", encryptPwd).add("salt", salt), Cnd.where("id", "=", user.getId())); + } + this.clearCache(); + return users.size(); + } + /** * @param userId * @param pid diff --git a/src/main/resources/views/platform/sys/user/index.html b/src/main/resources/views/platform/sys/user/index.html index 172e30c6..c5523fd7 100644 --- a/src/main/resources/views/platform/sys/user/index.html +++ b/src/main/resources/views/platform/sys/user/index.html @@ -28,6 +28,10 @@ layout("/layouts/platform.html"){ 新建用户 + + + 重置所有用户密码 + { + this.resetAllPwdLoading = true + this.$axios.post("/platform/sys/user/resetAllPwd", {}).then((res) => { + if (res.code === 0) { + this.$alert("已重置 " + res.data + " 个用户的密码", "重置完成", { + confirmButtonText: "确定" + }) + } + }).finally(() => { + this.resetAllPwdLoading = false + }) + }) + .catch(() => {}) + }, doAdd() { this.$refs["addForm"].validate((valid) => { if (valid) {