Merge remote-tracking branch 'origin/main'

This commit is contained in:
2026-06-25 14:24:55 +08:00
5 changed files with 109 additions and 4 deletions
@@ -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);
}
@@ -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")
@@ -78,6 +78,14 @@ public interface SysUserService extends BaseService<Sys_user> {
*/
void deleteByIds(String[] userIds);
/**
* 重置所有普通用户密码,系统内置 superadmin 账号不参与重置。
* 返回值为本次实际完成密码重置的用户数量,便于前端提示管理员操作影响范围。
*
* @return 已重置密码的用户数量
*/
int resetAllUserPwdExcludeSuperadmin();
/**
* 通过用户ID和菜单父ID获取下级权限菜单
*
@@ -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<Sys_user> implements Sys
dao().clear("sys_user", Cnd.where("id", "in", userIds));
}
/**
* 批量重置普通用户密码。
* 业务边界:superadmin 为系统内置管理员账号,必须保持原密码不被批量操作影响。
*
* @return 实际重置密码的用户数量
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public int resetAllUserPwdExcludeSuperadmin() {
List<Sys_user> 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
@@ -28,6 +28,10 @@ layout("/layouts/platform.html"){
<i class="ti-plus"></i>
新建用户
</el-button>
<el-button size="small" @click="resetAllPwd" :loading="resetAllPwdLoading" type="warning">
<i class="ti-reload"></i>
重置所有用户密码
</el-button>
</table-tool>
<el-table
:key="tableKey"
@@ -208,6 +212,7 @@ layout("/layouts/platform.html"){
addDialogVisible: false,
editDialogVisible: false,
roleDialogVisible: false,
resetAllPwdLoading: false,
treeData: {
label: "name",
children: "zones",
@@ -321,6 +326,26 @@ layout("/layouts/platform.html"){
this.formData = {} //打开新增窗口,表单先清空
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
},
resetAllPwd() {
this.$confirm("此操作将重置除 superadmin 外所有用户的密码,确定继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
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) {