fix: 优化登录逻辑

This commit is contained in:
tangwei 2026-08-03 10:05:56 +08:00
parent a5fc9d3b37
commit 7ba5c1b1db
18 changed files with 439 additions and 47 deletions

View File

@ -17,7 +17,8 @@ public interface SdFpssBHMapper extends BaseMapper<SdFpssBH> {
"WHERE 1=1 " + "WHERE 1=1 " +
"<if test='baseId != null and baseId != \"\"'> AND E.BASE_ID = #{baseId} </if>" + "<if test='baseId != null and baseId != \"\"'> AND E.BASE_ID = #{baseId} </if>" +
"<if test='rstcd != null and rstcd != \"\"'> AND F.RSTCD = #{rstcd} </if>" + "<if test='rstcd != null and rstcd != \"\"'> AND F.RSTCD = #{rstcd} </if>" +
"<if test='rvcd != null and rvcd != \"\"'> AND E.REACHCD = #{rvcd} </if>" + "<if test='rvcd != null and rvcd != \"\"'> AND E.RVCD = #{rvcd} </if>" +
"<if test='reachcd != null and reachcd != \"\"'> AND E.REACHCD = #{reachcd} </if>" +
// "<if test='rstcd != null and rstcd != \"\"'> AND F.RSTCD = #{rstcd} </if>" + // "<if test='rstcd != null and rstcd != \"\"'> AND F.RSTCD = #{rstcd} </if>" +
"<if test='stnm != null and stnm != \"\"'> AND F.STNM LIKE '%' || #{stnm} || '%' </if>" + "<if test='stnm != null and stnm != \"\"'> AND F.STNM LIKE '%' || #{stnm} || '%' </if>" +
"ORDER BY F.ORDER_INDEX DESC" + "ORDER BY F.ORDER_INDEX DESC" +

View File

@ -37,6 +37,7 @@ import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -100,8 +101,12 @@ public class LoginController {
Integer status = loginUser.getUser().getStatus(); Integer status = loginUser.getUser().getStatus();
String regStatus = loginUser.getUser().getRegStatus(); String regStatus = loginUser.getUser().getRegStatus();
if (StrUtil.isNotBlank(tenantId)&&!tenantId.equals(loginUser.getUser().getTenantId())) { // 多门户验证用户是否有权限访问指定门户
return ResponseResult.error("账号不存在或密码错误"); if (!loginUser.isSuperAdmin() && StrUtil.isNotBlank(tenantId)) {
List<String> accessibleIds = loginUser.getAccessibleTenantIds();
if (accessibleIds == null || !accessibleIds.contains(tenantId)) {
return ResponseResult.error("账号不存在或密码错误");
}
} }
if (StrUtil.isNotBlank(regStatus)&&"REJECTED".equals(regStatus)) { if (StrUtil.isNotBlank(regStatus)&&"REJECTED".equals(regStatus)) {
@ -149,6 +154,10 @@ public class LoginController {
String token = JWTUtil.createToken(map, "12345678".getBytes()); String token = JWTUtil.createToken(map, "12345678".getBytes());
map.put("token", token); map.put("token", token);
// 返回可访问门户列表和超级管理员标识
map.put("accessibleTenantIds", loginUser.getAccessibleTenantIds());
map.put("superAdmin", loginUser.isSuperAdmin());
map.put("currentTenantId", tenantId);
//把完整的用户信息存入到HuTool缓存中userId作为key //把完整的用户信息存入到HuTool缓存中userId作为key
String jsonStr = JSONUtil.toJsonStr(loginUser); String jsonStr = JSONUtil.toJsonStr(loginUser);
webConfig.loginuserCache().put("login:" + userId, jsonStr); webConfig.loginuserCache().put("login:" + userId, jsonStr);

View File

@ -11,6 +11,7 @@ import com.yfd.platform.qgc_base.service.ISdEngInfoBHService;
import com.yfd.platform.qgc_base.service.ISdHbrvDicService; import com.yfd.platform.qgc_base.service.ISdHbrvDicService;
import com.yfd.platform.system.domain.*; import com.yfd.platform.system.domain.*;
import com.yfd.platform.system.mapper.SysMenuMapper; import com.yfd.platform.system.mapper.SysMenuMapper;
import com.yfd.platform.system.mapper.SysUserTenantMapper;
import com.yfd.platform.system.service.ISmsVerifyCodeService; import com.yfd.platform.system.service.ISmsVerifyCodeService;
import com.yfd.platform.system.service.ISysLogService; import com.yfd.platform.system.service.ISysLogService;
import com.yfd.platform.system.service.IUserService; import com.yfd.platform.system.service.IUserService;
@ -66,6 +67,10 @@ public class SmsVerifyCodeController {
@Resource @Resource
private ISdEngInfoBHService engInfoBHService; private ISdEngInfoBHService engInfoBHService;
@Resource
private SysUserTenantMapper sysUserTenantMapper;
@Resource @Resource
private ISdHbrvDicService hbrvDicService; private ISdHbrvDicService hbrvDicService;
@ -441,8 +446,14 @@ public class SmsVerifyCodeController {
loginUser.setUser(user); loginUser.setUser(user);
loginUser.setUsername(user.getUsername()); loginUser.setUsername(user.getUsername());
//Todo 根据用户查询权限信息 添加到LoginUser中 //Todo 根据用户查询权限信息 添加到LoginUser中
List<String> permissions = // 加载权限超级管理员加载全部权限普通用户按门户过滤
sysMenuMapper.selectPermsByUserId(user.getId()); boolean isSuperAdmin = userService.isSuperAdmin(user.getId());
List<String> permissions;
if (isSuperAdmin) {
permissions = sysMenuMapper.selectPermsByUserId(user.getId(), null);
} else {
permissions = sysMenuMapper.selectPermsByUserId(user.getId(), tenantId);
}
loginUser.setPermissions( permissions); loginUser.setPermissions( permissions);
HttpServletRequest request = RequestHolder.getHttpServletRequest(); HttpServletRequest request = RequestHolder.getHttpServletRequest();
SysLog sysLog = new SysLog(); SysLog sysLog = new SysLog();

View File

@ -115,7 +115,7 @@ public class SysMenuController {
if (0 != userInfo.getUsertype()) { if (0 != userInfo.getUsertype()) {
id = userInfo.getId(); id = userInfo.getId();
} }
return sysMenuService.getMenuTree(id, StrUtil.isNotBlank(tenantId) ? StrUtil.trimToNull(tenantId) : userInfo.getTenantId()); return sysMenuService.getMenuTree(id, tenantId);
} }
/*********************************** /***********************************

View File

@ -17,6 +17,7 @@ import org.springframework.web.multipart.MultipartFile;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -60,7 +61,7 @@ public class UserController {
if (StrUtil.isEmpty(user.getId())) { if (StrUtil.isEmpty(user.getId())) {
return ResponseResult.error("没有用户ID"); return ResponseResult.error("没有用户ID");
} }
user.setTenantId(StrUtil.trimToNull(tenantId)); // user.setTenantId(StrUtil.trimToNull(tenantId));
//填写 当前用户名称 //填写 当前用户名称
user.setLastmodifier(userService.getUsername()); user.setLastmodifier(userService.getUsername());
//填写 当前日期 //填写 当前日期
@ -115,8 +116,8 @@ public class UserController {
public ResponseResult queryUserById(String id, public ResponseResult queryUserById(String id,
@RequestHeader(value = "Tenant_id", required = false) String tenantId) { @RequestHeader(value = "Tenant_id", required = false) String tenantId) {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getId, id) queryWrapper.eq(SysUser::getId, id);
.eq(StrUtil.isNotBlank(tenantId), SysUser::getTenantId, StrUtil.trim(tenantId)); // .eq(StrUtil.isNotBlank(tenantId), SysUser::getTenantId, StrUtil.trim(tenantId));
SysUser user = userService.getOne(queryWrapper); SysUser user = userService.getOne(queryWrapper);
return ResponseResult.successData(user); return ResponseResult.successData(user);
} }
@ -251,4 +252,54 @@ public class UserController {
Page<SysUser> result = userService.queryPendingAuditUsers(page, name, regStatus, StrUtil.trimToNull(tenantId)); Page<SysUser> result = userService.queryPendingAuditUsers(page, name, regStatus, StrUtil.trimToNull(tenantId));
return ResponseResult.successData(result); return ResponseResult.successData(result);
} }
// ==================== 多门户管理 ====================
/***********************************
* 用途说明为用户分配门户
* 参数说明 userId 用户ID, tenantIds 门户ID列表逗号分隔
************************************/
@Log(module = "系统用户", value = "分配门户")
@PostMapping("/assignTenant")
@Operation(summary = "为用户分配门户")
@ResponseBody
public ResponseResult assignTenant(String userId, String tenantIds) {
if (StrUtil.isBlank(userId) || StrUtil.isBlank(tenantIds)) {
return ResponseResult.error("用户ID和门户ID不能为空");
}
List<String> tenantIdList = List.of(tenantIds.split(","));
userService.assignTenantsToUser(userId, tenantIdList);
return ResponseResult.success();
}
/***********************************
* 用途说明移除用户的门户关联
* 参数说明 userId 用户ID, tenantId 门户ID
************************************/
@Log(module = "系统用户", value = "移除门户")
@PostMapping("/removeTenant")
@Operation(summary = "移除用户的门户关联")
@ResponseBody
public ResponseResult removeTenant(String userId, String tenantId) {
if (StrUtil.isBlank(userId) || StrUtil.isBlank(tenantId)) {
return ResponseResult.error("用户ID和门户ID不能为空");
}
userService.removeTenantFromUser(userId, tenantId);
return ResponseResult.success();
}
/***********************************
* 用途说明获取用户关联的门户列表
* 参数说明 userId 用户ID
************************************/
@GetMapping("/getUserTenants")
@Operation(summary = "获取用户关联的门户列表")
@ResponseBody
public ResponseResult getUserTenants(String userId) {
if (StrUtil.isBlank(userId)) {
return ResponseResult.error("用户ID不能为空");
}
List<String> tenants = userService.getUserTenants(userId);
return ResponseResult.successData(tenants);
}
} }

View File

@ -22,19 +22,44 @@ public class LoginUser implements UserDetails {
private String username; private String username;
private List<String> permissions=new ArrayList<>(); private List<String> permissions = new ArrayList<>();
/**
* 当前登录的门户ID
*/
private String currentTenantId;
/**
* 用户可访问的门户ID列表用于门户切换
*/
private List<String> accessibleTenantIds;
/**
* 是否超级管理员LEVEL=1
*/
private boolean superAdmin;
/** /**
* 自定义构造函数如果需要特殊逻辑 * 自定义构造函数如果需要特殊逻辑
*/ */
public LoginUser(SysUser user, List<String> permissions) { public LoginUser(SysUser user, List<String> permissions) {
this.user = user; this.user = user;
// 4. 增加非空判断确保 permissions 永远不为 null
if (permissions != null) { if (permissions != null) {
this.permissions = permissions; this.permissions = permissions;
} }
} }
public LoginUser(SysUser user, List<String> permissions,
String currentTenantId, List<String> accessibleTenantIds, boolean superAdmin) {
this.user = user;
if (permissions != null) {
this.permissions = permissions;
}
this.currentTenantId = currentTenantId;
this.accessibleTenantIds = accessibleTenantIds;
this.superAdmin = superAdmin;
}
@JSONField(serialize = false) @JSONField(serialize = false)
private List<SimpleGrantedAuthority> authorities; private List<SimpleGrantedAuthority> authorities;

View File

@ -0,0 +1,30 @@
package com.yfd.platform.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 用户-门户关联表
* </p>
*/
@Data
@TableName("SYS_USER_TENANT")
public class SysUserTenant implements Serializable {
private static final long serialVersionUID = 1L;
/** 主键 */
@TableId(type = IdType.ASSIGN_UUID)
private String id;
/** 用户ID */
private String userId;
/** 门户ID */
private String tenantId;
}

View File

@ -44,7 +44,7 @@ public interface SysMenuMapper extends BaseMapper<SysMenu> {
@Param("tenantId") String tenantId); @Param("tenantId") String tenantId);
List<String> selectPermsByUserId(String userId); List<String> selectPermsByUserId(@Param("userId") String userId, @Param("tenantId") String tenantId);
//List<SysMenu> selectMenuByUserId(String userId); //List<SysMenu> selectMenuByUserId(String userId);
List<SysMenu> selectMenuByUserId(@Param("userId") String userId, @Param("tenantId") String tenantId); List<SysMenu> selectMenuByUserId(@Param("userId") String userId, @Param("tenantId") String tenantId);

View File

@ -0,0 +1,47 @@
package com.yfd.platform.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yfd.platform.system.domain.SysUserTenant;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* 用户-门户关联表 Mapper 接口
* </p>
*/
@Mapper
public interface SysUserTenantMapper extends BaseMapper<SysUserTenant> {
/**
* 查询用户可访问的门户ID列表
*/
List<String> getTenantIdsByUserId(@Param("userId") String userId);
/**
* 批量删除用户-门户关联
*/
int deleteByUserId(@Param("userId") String userId);
/**
* 批量新增用户-门户关联
*/
int batchInsert(@Param("userId") String userId, @Param("tenantIds") List<String> tenantIds);
/**
* 查询某门户下的所有用户ID
*/
List<String> getUserIdsByTenantId(@Param("tenantId") String tenantId);
/**
* 删除指定用户和指定门户的关联
*/
int deleteByUserIdAndTenantId(@Param("userId") String userId, @Param("tenantId") String tenantId);
/**
* 批量查询用户-门户关联用于用户列表展示
*/
List<java.util.Map<String, Object>> getTenantIdsByUserIds(@Param("userIds") List<String> userIds);
}

View File

@ -184,4 +184,23 @@ public interface IUserService extends IService<SysUser> {
Page<SysUser> queryPendingAuditUsers(Page<SysUser> page, String name, String regStatus, String tenantId); Page<SysUser> queryPendingAuditUsers(Page<SysUser> page, String name, String regStatus, String tenantId);
List<SysUser> queryUsersList(String name, String tenantId); List<SysUser> queryUsersList(String name, String tenantId);
// ==================== 多门户管理 ====================
/**
* 为用户分配门户
*/
void assignTenantsToUser(String userId, List<String> tenantIds);
/**
* 移除用户的某个门户关联
*/
void removeTenantFromUser(String userId, String tenantId);
/**
* 获取用户关联的门户ID列表
*/
List<String> getUserTenants(String userId);
boolean isSuperAdmin(String userId);
} }

View File

@ -38,17 +38,17 @@ public class AdminAuthServiceImpl implements IAdminAuthService {
public List<String> getSuperAdminUsernames() { public List<String> getSuperAdminUsernames() {
// 获取当前请求 // 获取当前请求
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); // ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getUsertype, 0).select(SysUser::getUsername); queryWrapper.eq(SysUser::getUsertype, 0).select(SysUser::getUsername);
//根据用户名称或手机号查询用户信息 //根据用户名称或手机号查询用户信息
if (attributes != null) { // if (attributes != null) {
HttpServletRequest request = attributes.getRequest(); // HttpServletRequest request = attributes.getRequest();
String tenantId = request.getHeader("Tenant_Id"); // String tenantId = request.getHeader("Tenant_Id");
if(StrUtil.isNotBlank(tenantId)){ // if(StrUtil.isNotBlank(tenantId)){
queryWrapper.eq(SysUser::getTenantId, tenantId); // queryWrapper.eq(SysUser::getTenantId, tenantId);
} // }
} // }
List<SysUser> userList = userMapper.selectList(queryWrapper); List<SysUser> userList = userMapper.selectList(queryWrapper);
if (CollUtil.isEmpty(userList)) { if (CollUtil.isEmpty(userList)) {
return new ArrayList<>(); return new ArrayList<>();

View File

@ -48,7 +48,7 @@ public class SmsVerifyCodeServiceImpl extends ServiceImpl<SmsVerifyCodeMapper, S
LambdaQueryWrapper<SmsVerifyCode> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SmsVerifyCode> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SmsVerifyCode::getPhone, phone) queryWrapper.eq(SmsVerifyCode::getPhone, phone)
.eq(SmsVerifyCode::getType, type) .eq(SmsVerifyCode::getType, type)
.gt(SmsVerifyCode::getTenantId, tenantId) .eq(SmsVerifyCode::getTenantId, tenantId)
.eq(SmsVerifyCode::getStatus, SmsVerifyCode.STATUS_UNUSED); .eq(SmsVerifyCode::getStatus, SmsVerifyCode.STATUS_UNUSED);
this.remove(queryWrapper); this.remove(queryWrapper);
@ -161,7 +161,7 @@ public class SmsVerifyCodeServiceImpl extends ServiceImpl<SmsVerifyCodeMapper, S
} }
List<String> ids = userIds.stream().distinct().toList(); List<String> ids = userIds.stream().distinct().toList();
List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getId, ids) List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getId, ids)
.eq(SysUser::getRegStatus, "APPROVED").eq(SysUser::getTenantId, tenantId).eq(SysUser::getStatus,1).select(SysUser::getPhone)); .eq(SysUser::getRegStatus, "APPROVED").eq(SysUser::getStatus,1).select(SysUser::getPhone));
if (sysUsers.isEmpty()) { if (sysUsers.isEmpty()) {
log.warn("催促短信发送失败未找到有效的手机号userIds: {}", ids); log.warn("催促短信发送失败未找到有效的手机号userIds: {}", ids);

View File

@ -3,12 +3,12 @@ package com.yfd.platform.system.service.impl;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yfd.platform.datasource.DataSource;
import com.yfd.platform.datasource.DataSourceKeys;
import com.yfd.platform.datasource.TargetDataSource; import com.yfd.platform.datasource.TargetDataSource;
import com.yfd.platform.system.domain.LoginUser; import com.yfd.platform.system.domain.LoginUser;
import com.yfd.platform.system.domain.SysUser; import com.yfd.platform.system.domain.SysUser;
import com.yfd.platform.system.mapper.SysMenuMapper; import com.yfd.platform.system.mapper.SysMenuMapper;
import com.yfd.platform.system.mapper.SysUserMapper;
import com.yfd.platform.system.mapper.SysUserTenantMapper;
import com.yfd.platform.system.service.IUserService; import com.yfd.platform.system.service.IUserService;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
@ -20,11 +20,14 @@ import jakarta.annotation.Resource;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* <p> * <p>
* 用户服务实现类 继承UserDetailsService 实现接口 * 用户服务实现类 继承UserDetailsService 实现接口
* 支持多门户登录用户可关联多个门户登录时选择其中一个门户
* 超级管理员LEVEL=1拥有跨所有门户的权限
* </p> * </p>
* *
* @author zhengsl * @author zhengsl
@ -39,31 +42,68 @@ public class UserDetailsServiceImpl implements UserDetailsService {
@Resource @Resource
private SysMenuMapper sysMenuMapper; private SysMenuMapper sysMenuMapper;
@Resource
private SysUserTenantMapper sysUserTenantMapper;
@Resource
private SysUserMapper sysUserMapper;
@Override @Override
@TargetDataSource() @TargetDataSource()
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 获取当前请求 // 获取当前请求
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//根据用户名称或手机号查询用户信息
// 根据用户名称或手机号查询用户信息不加tenantId过滤支持跨门户登录
QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>(); QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
queryWrapper.and(wrapper -> wrapper.eq("username", username).or().eq("phone", username)); queryWrapper.and(wrapper -> wrapper.eq("username", username).or().eq("phone", username));
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
String tenantId = request.getHeader("Tenant_Id");
if(StrUtil.isNotBlank(tenantId)){
queryWrapper.eq("TENANT_ID", tenantId);
}
}
SysUser user = userService.getOne(queryWrapper); SysUser user = userService.getOne(queryWrapper);
if (ObjectUtil.isEmpty(user)) { if (ObjectUtil.isEmpty(user)) {
throw new RuntimeException("用户账号不存在!"); throw new RuntimeException("用户账号不存在!");
} }
//Todo 根据用户查询权限信息 添加到LoginUser中
List<String> permissions =
sysMenuMapper.selectPermsByUserId(user.getId());
//封装成UserDetails对象返回 // 获取请求中的门户ID
return new LoginUser(user,permissions); String tenantId = null;
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
tenantId = request.getHeader("Tenant_Id");
}
// 判断是否为超级管理员LEVEL=1
boolean isSuperAdmin = isSuperAdmin(user.getId());
// 查询用户可访问的门户列表
List<String> accessibleTenantIds = sysUserTenantMapper.getTenantIdsByUserId(user.getId());
// 非超级管理员必须指定门户且必须在可访问列表中
if (!isSuperAdmin) {
if (StrUtil.isBlank(tenantId)) {
throw new RuntimeException("普通用户登录必须指定门户(Tenant_Id)");
}
if (accessibleTenantIds == null || !accessibleTenantIds.contains(tenantId)) {
throw new RuntimeException("用户无权限访问该门户");
}
}
// 加载权限超级管理员加载全部权限普通用户按门户过滤
List<String> permissions;
if (isSuperAdmin) {
permissions = sysMenuMapper.selectPermsByUserId(user.getId(), null);
} else {
permissions = sysMenuMapper.selectPermsByUserId(user.getId(), tenantId);
}
// 封装成UserDetails对象返回包含当前门户和可访问门户列表
return new LoginUser(user, permissions, tenantId, accessibleTenantIds, isSuperAdmin);
}
/**
* 判断用户是否为超级管理员拥有LEVEL=1的角色
*/
private boolean isSuperAdmin(String userId) {
String maxLevel = sysUserMapper.getMaxLevel(userId);
return "1".equals(maxLevel);
} }
} }

View File

@ -22,6 +22,7 @@ import com.yfd.platform.system.domain.SysRole;
import com.yfd.platform.system.domain.SysUser; import com.yfd.platform.system.domain.SysUser;
import com.yfd.platform.system.mapper.SysRoleMapper; import com.yfd.platform.system.mapper.SysRoleMapper;
import com.yfd.platform.system.mapper.SysUserMapper; import com.yfd.platform.system.mapper.SysUserMapper;
import com.yfd.platform.system.mapper.SysUserTenantMapper;
import com.yfd.platform.system.service.IAdminAuthService; import com.yfd.platform.system.service.IAdminAuthService;
import com.yfd.platform.system.service.IUserService; import com.yfd.platform.system.service.IUserService;
import com.yfd.platform.utils.FileUtil; import com.yfd.platform.utils.FileUtil;
@ -81,6 +82,9 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
@Resource @Resource
private SysUserDataScopeMapper sysUserDataScopeMapper; private SysUserDataScopeMapper sysUserDataScopeMapper;
@Resource
private SysUserTenantMapper sysUserTenantMapper;
@Resource @Resource
private IAdminAuthService adminAuthService; private IAdminAuthService adminAuthService;
@ -169,7 +173,7 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
//账号有效 //账号有效
sysUser.setStatus(1); sysUser.setStatus(1);
//判断注册的登录账号是否存在 //判断注册的登录账号是否存在
if (isExistAccount(sysUser.getUsername(),sysUser.getTenantId() )) { if (isExistAccount(sysUser.getUsername())) {
//新增用户 //新增用户
boolean ok = this.save(sysUser); boolean ok = this.save(sysUser);
//新增用户分配权限 //新增用户分配权限
@ -185,6 +189,13 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
} }
//判断新增是否成功 消息提示 //判断新增是否成功 消息提示
if (ok) { if (ok) {
// 插入用户-门户关联
String tenantId = sysUser.getTenantId();
if (StrUtil.isNotBlank(tenantId)) {
List<String> tenantIds = new ArrayList<>();
tenantIds.add(tenantId);
sysUserTenantMapper.batchInsert(sysUser.getId(), tenantIds);
}
result.put("status", "sucess"); result.put("status", "sucess");
result.put("msg", "新增用户成功!"); result.put("msg", "新增用户成功!");
@ -434,6 +445,8 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
if (isOk) { if (isOk) {
//根据用户id 删除该用户角色关联 //根据用户id 删除该用户角色关联
sysUserMapper.delRoleUsersByUserid(id); sysUserMapper.delRoleUsersByUserid(id);
// 删除用户-门户关联
sysUserTenantMapper.deleteByUserId(id);
//判断是否存在 账号头像 存在删除 //判断是否存在 账号头像 存在删除
if (StrUtil.isNotEmpty(sysUser.getAvatar())) { if (StrUtil.isNotEmpty(sysUser.getAvatar())) {
FileUtil.del(imgName); FileUtil.del(imgName);
@ -636,6 +649,10 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
} }
// 根据ID删除用户与角色的关联信息 // 根据ID删除用户与角色的关联信息
sysUserMapper.delRoleUsersByUserIds(ids); sysUserMapper.delRoleUsersByUserIds(ids);
// 删除用户-门户关联
for (String userId : ids) {
sysUserTenantMapper.deleteByUserId(userId);
}
List<String> avatars = List<String> avatars =
sysUsers.stream().map(SysUser::getAvatar).collect(Collectors.toList()); sysUsers.stream().map(SysUser::getAvatar).collect(Collectors.toList());
if (avatars.size() > 0) { if (avatars.size() > 0) {
@ -654,7 +671,7 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
public SysUser getUserByPhone(String phone,String tenantId) { public SysUser getUserByPhone(String phone,String tenantId) {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getPhone, phone); queryWrapper.eq(SysUser::getPhone, phone);
queryWrapper.eq(SysUser::getTenantId, tenantId); // queryWrapper.eq(SysUser::getTenantId, tenantId);
return this.getOne(queryWrapper); return this.getOne(queryWrapper);
} }
@ -893,15 +910,14 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
} }
/*********************************** /***********************************
* 用途说明:比较登录名称是否有重复 * 用途说明:比较登录名称是否有重复全局唯一不区分门户
* 参数说明 * 参数说明
* account 登录名称 * account 登录名称
* 返回值说明: 重复返回 false 否则返回 true * 返回值说明: 重复返回 false 否则返回 true
************************************/ ************************************/
private boolean isExistAccount(String username,String tenantId) { private boolean isExistAccount(String username) {
QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>(); QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
if (this.list(queryWrapper.eq("username", username).eq("TENANT_ID", tenantId)).size() > 0) { if (this.list(queryWrapper.eq("username", username)).size() > 0) {
//判断 查询登录账号 结果集是否为null 重复返回 false 否则返回 tree
return false; return false;
} else { } else {
return true; return true;
@ -912,7 +928,7 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
@Override @Override
public List<SysUser> queryUsersList(String name, String tenantId) { public List<SysUser> queryUsersList(String name, String tenantId) {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(tenantId), SysUser::getTenantId, tenantId); // queryWrapper.eq(StrUtil.isNotBlank(tenantId), SysUser::getTenantId, tenantId);
queryWrapper.eq(SysUser::getStatus, 1); queryWrapper.eq(SysUser::getStatus, 1);
queryWrapper.and(StrUtil.isNotBlank(name), wrapper -> queryWrapper.and(StrUtil.isNotBlank(name), wrapper ->
wrapper.like(SysUser::getNickname, name) wrapper.like(SysUser::getNickname, name)
@ -923,4 +939,49 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
List<SysUser> sysUserList = this.list( queryWrapper); List<SysUser> sysUserList = this.list( queryWrapper);
return sysUserList; return sysUserList;
} }
// ==================== 多门户管理 ====================
/**
* 为用户分配门户
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void assignTenantsToUser(String userId, List<String> tenantIds) {
if (StrUtil.isBlank(userId) || tenantIds == null || tenantIds.isEmpty()) {
throw new RuntimeException("用户ID和门户ID列表不能为空");
}
sysUserTenantMapper.batchInsert(userId, tenantIds);
}
/**
* 移除用户的某个门户关联
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void removeTenantFromUser(String userId, String tenantId) {
if (StrUtil.isBlank(userId) || StrUtil.isBlank(tenantId)) {
throw new RuntimeException("用户ID和门户ID不能为空");
}
sysUserTenantMapper.deleteByUserIdAndTenantId(userId, tenantId);
}
/**
* 获取用户关联的门户ID列表
*/
@Override
public List<String> getUserTenants(String userId) {
if (StrUtil.isBlank(userId)) {
return new ArrayList<>();
}
return sysUserTenantMapper.getTenantIdsByUserId(userId);
}
public boolean isSuperAdmin(String userId) {
// String maxLevel = sysUserMapper.getMaxLevel(userId);
SysUser sysUser = sysUserMapper.selectById(userId);
return sysUser!=null && sysUser.getUsertype()==0;
}
} }

View File

@ -19,6 +19,7 @@ import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.yfd.platform.exception.BadRequestException; import com.yfd.platform.exception.BadRequestException;
import com.yfd.platform.system.domain.LoginUser;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -105,4 +106,40 @@ public class SecurityUtils {
.anyMatch(auth -> permission.equals(auth.getAuthority())); .anyMatch(auth -> permission.equals(auth.getAuthority()));
} }
/**
* 获取当前登录用户的门户ID
* @return 门户ID超级管理员可能返回null
*/
public static String getCurrentTenantId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !(authentication.getPrincipal() instanceof LoginUser)) {
return null;
}
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
return loginUser.getCurrentTenantId();
}
/**
* 判断当前用户是否为超级管理员
*/
public static boolean isSuperAdmin() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !(authentication.getPrincipal() instanceof LoginUser)) {
return false;
}
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
return loginUser.isSuperAdmin();
}
/**
* 获取当前用户可访问的门户ID列表
*/
public static List<String> getAccessibleTenantIds() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !(authentication.getPrincipal() instanceof LoginUser)) {
return null;
}
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
return loginUser.getAccessibleTenantIds();
}
} }

View File

@ -27,7 +27,7 @@
</update> </update>
<select id="selectPermsByUserId" resultType="java.lang.String"> <select id="selectPermsByUserId" resultType="java.lang.String">
SELECT SELECT
permission permission
FROM FROM
sys_role_users ru sys_role_users ru
@ -38,7 +38,10 @@
r.isvaild = 1 r.isvaild = 1
AND ru.userid = #{userId} AND ru.userid = #{userId}
AND permission IS NOT NULL AND permission IS NOT NULL
-- AND permission != '' <if test="tenantId != null and tenantId != ''">
AND r.tenant_id = #{tenantId}
AND m.tenant_id = #{tenantId}
</if>
</select> </select>
<select id="selectMenuByUserId" <select id="selectMenuByUserId"

View File

@ -73,6 +73,7 @@
u.lastmodifydate u.lastmodifydate
FROM FROM
sys_user u sys_user u
LEFT JOIN SYS_USER_TENANT ut ON u.id = ut.USER_ID
WHERE WHERE
1 = 1 1 = 1
AND ( ( u.REG_STATUS != 'PENDING' AND u.REG_STATUS != 'REJECTED' ) OR u.REG_STATUS IS NULL ) AND ( ( u.REG_STATUS != 'PENDING' AND u.REG_STATUS != 'REJECTED' ) OR u.REG_STATUS IS NULL )
@ -84,7 +85,7 @@
and u.username LIKE '%' || #{username} || '%' and u.username LIKE '%' || #{username} || '%'
</if> </if>
<if test="tenantId != null and tenantId != ''"> <if test="tenantId != null and tenantId != ''">
and u.tenant_id = #{tenantId} and (ut.TENANT_ID = #{tenantId} OR u.tenant_id = #{tenantId})
</if> </if>
ORDER BY u.lastmodifydate DESC ORDER BY u.lastmodifydate DESC
</select> </select>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yfd.platform.system.mapper.SysUserTenantMapper">
<!-- 查询用户可访问的门户ID列表 -->
<select id="getTenantIdsByUserId" resultType="java.lang.String">
SELECT TENANT_ID
FROM SYS_USER_TENANT
WHERE USER_ID = #{userId}
</select>
<!-- 批量删除用户-门户关联 -->
<delete id="deleteByUserId">
DELETE FROM SYS_USER_TENANT WHERE USER_ID = #{userId}
</delete>
<!-- 批量新增用户-门户关联(使用 MERGE 兼容 Oracle -->
<insert id="batchInsert">
MERGE INTO SYS_USER_TENANT T
USING (
<foreach collection="tenantIds" item="tenantId" index="index" separator="UNION ALL">
SELECT
#{userId, jdbcType=VARCHAR} AS USER_ID,
#{tenantId, jdbcType=VARCHAR} AS TENANT_ID
FROM DUAL
</foreach>
) S
ON (T.USER_ID = S.USER_ID AND T.TENANT_ID = S.TENANT_ID)
WHEN NOT MATCHED THEN
INSERT (ID, USER_ID, TENANT_ID)
VALUES (SYS_GUID(), S.USER_ID, S.TENANT_ID)
</insert>
<!-- 删除指定用户和指定门户的关联 -->
<delete id="deleteByUserIdAndTenantId">
DELETE FROM SYS_USER_TENANT WHERE USER_ID = #{userId} AND TENANT_ID = #{tenantId}
</delete>
<!-- 查询某门户下的所有用户ID -->
<select id="getUserIdsByTenantId" resultType="java.lang.String">
SELECT USER_ID FROM SYS_USER_TENANT WHERE TENANT_ID = #{tenantId}
</select>
<!-- 批量查询用户-门户关联 -->
<select id="getTenantIdsByUserIds" resultType="java.util.HashMap">
SELECT
USER_ID AS "userId",
TENANT_ID AS "tenantId"
FROM SYS_USER_TENANT
WHERE USER_ID IN
<foreach collection="userIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
</mapper>