mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-21 02:25:56 +08:00
add 框架整体 整合适配多租户功能
This commit is contained in:
parent
39d74a7780
commit
5b08bba16c
@ -41,16 +41,18 @@ public class SysLoginController {
|
|||||||
/**
|
/**
|
||||||
* 登录方法
|
* 登录方法
|
||||||
*
|
*
|
||||||
* @param loginBody 登录信息
|
* @param body 登录信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@SaIgnore
|
@SaIgnore
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
public R<LoginVo> login(@Validated @RequestBody LoginBody loginBody) {
|
public R<LoginVo> login(@Validated @RequestBody LoginBody body) {
|
||||||
LoginVo loginVo = new LoginVo();
|
LoginVo loginVo = new LoginVo();
|
||||||
// 生成令牌
|
// 生成令牌
|
||||||
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
|
String token = loginService.login(
|
||||||
loginBody.getUuid());
|
body.getTenantId(),
|
||||||
|
body.getUsername(), body.getPassword(),
|
||||||
|
body.getCode(), body.getUuid());
|
||||||
loginVo.setToken(token);
|
loginVo.setToken(token);
|
||||||
return R.ok(loginVo);
|
return R.ok(loginVo);
|
||||||
}
|
}
|
||||||
@ -58,15 +60,15 @@ public class SysLoginController {
|
|||||||
/**
|
/**
|
||||||
* 短信登录(示例)
|
* 短信登录(示例)
|
||||||
*
|
*
|
||||||
* @param smsLoginBody 登录信息
|
* @param body 登录信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@SaIgnore
|
@SaIgnore
|
||||||
@PostMapping("/smsLogin")
|
@PostMapping("/smsLogin")
|
||||||
public R<LoginVo> smsLogin(@Validated @RequestBody SmsLoginBody smsLoginBody) {
|
public R<LoginVo> smsLogin(@Validated @RequestBody SmsLoginBody body) {
|
||||||
LoginVo loginVo = new LoginVo();
|
LoginVo loginVo = new LoginVo();
|
||||||
// 生成令牌
|
// 生成令牌
|
||||||
String token = loginService.smsLogin(smsLoginBody.getPhonenumber(), smsLoginBody.getSmsCode());
|
String token = loginService.smsLogin(body.getTenantId(), body.getPhonenumber(), body.getSmsCode());
|
||||||
loginVo.setToken(token);
|
loginVo.setToken(token);
|
||||||
return R.ok(loginVo);
|
return R.ok(loginVo);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,9 @@ import com.ruoyi.common.core.domain.model.LoginUser;
|
|||||||
import com.ruoyi.common.core.domain.model.XcxLoginUser;
|
import com.ruoyi.common.core.domain.model.XcxLoginUser;
|
||||||
import com.ruoyi.common.core.enums.DeviceType;
|
import com.ruoyi.common.core.enums.DeviceType;
|
||||||
import com.ruoyi.common.core.enums.LoginType;
|
import com.ruoyi.common.core.enums.LoginType;
|
||||||
|
import com.ruoyi.common.core.enums.TenantStatus;
|
||||||
import com.ruoyi.common.core.enums.UserStatus;
|
import com.ruoyi.common.core.enums.UserStatus;
|
||||||
|
import com.ruoyi.common.core.exception.TenantException;
|
||||||
import com.ruoyi.common.core.exception.user.CaptchaException;
|
import com.ruoyi.common.core.exception.user.CaptchaException;
|
||||||
import com.ruoyi.common.core.exception.user.CaptchaExpireException;
|
import com.ruoyi.common.core.exception.user.CaptchaExpireException;
|
||||||
import com.ruoyi.common.core.exception.user.UserException;
|
import com.ruoyi.common.core.exception.user.UserException;
|
||||||
@ -22,10 +24,12 @@ import com.ruoyi.common.log.event.LogininforEvent;
|
|||||||
import com.ruoyi.common.redis.utils.RedisUtils;
|
import com.ruoyi.common.redis.utils.RedisUtils;
|
||||||
import com.ruoyi.common.satoken.utils.LoginHelper;
|
import com.ruoyi.common.satoken.utils.LoginHelper;
|
||||||
import com.ruoyi.system.domain.SysUser;
|
import com.ruoyi.system.domain.SysUser;
|
||||||
|
import com.ruoyi.system.domain.vo.SysTenantVo;
|
||||||
import com.ruoyi.system.domain.vo.SysUserVo;
|
import com.ruoyi.system.domain.vo.SysUserVo;
|
||||||
import com.ruoyi.system.mapper.SysUserMapper;
|
import com.ruoyi.system.mapper.SysUserMapper;
|
||||||
import com.ruoyi.system.service.ISysConfigService;
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
import com.ruoyi.system.service.ISysPermissionService;
|
import com.ruoyi.system.service.ISysPermissionService;
|
||||||
|
import com.ruoyi.system.service.ISysTenantService;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -33,6 +37,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@ -49,6 +54,7 @@ public class SysLoginService {
|
|||||||
private final SysUserMapper userMapper;
|
private final SysUserMapper userMapper;
|
||||||
private final ISysConfigService configService;
|
private final ISysConfigService configService;
|
||||||
private final ISysPermissionService permissionService;
|
private final ISysPermissionService permissionService;
|
||||||
|
private final ISysTenantService tenantService;
|
||||||
|
|
||||||
@Value("${user.password.maxRetryCount}")
|
@Value("${user.password.maxRetryCount}")
|
||||||
private Integer maxRetryCount;
|
private Integer maxRetryCount;
|
||||||
@ -56,6 +62,9 @@ public class SysLoginService {
|
|||||||
@Value("${user.password.lockTime}")
|
@Value("${user.password.lockTime}")
|
||||||
private Integer lockTime;
|
private Integer lockTime;
|
||||||
|
|
||||||
|
@Value("${tenant.enable}")
|
||||||
|
private Boolean tenantEnable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录验证
|
* 登录验证
|
||||||
*
|
*
|
||||||
@ -65,36 +74,41 @@ public class SysLoginService {
|
|||||||
* @param uuid 唯一标识
|
* @param uuid 唯一标识
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String login(String username, String password, String code, String uuid) {
|
public String login(String tenantId, String username, String password, String code, String uuid) {
|
||||||
HttpServletRequest request = ServletUtils.getRequest();
|
HttpServletRequest request = ServletUtils.getRequest();
|
||||||
boolean captchaEnabled = configService.selectCaptchaEnabled();
|
boolean captchaEnabled = configService.selectCaptchaEnabled();
|
||||||
// 验证码开关
|
// 验证码开关
|
||||||
if (captchaEnabled) {
|
if (captchaEnabled) {
|
||||||
validateCaptcha(username, code, uuid, request);
|
validateCaptcha(tenantId, username, code, uuid, request);
|
||||||
}
|
}
|
||||||
SysUserVo user = loadUserByUsername(username);
|
// 校验租户
|
||||||
checkLogin(LoginType.PASSWORD, username, () -> !BCrypt.checkpw(password, user.getPassword()));
|
checkTenant(tenantId);
|
||||||
|
|
||||||
|
SysUserVo user = loadUserByUsername(tenantId, username);
|
||||||
|
checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword()));
|
||||||
// 此处可根据登录用户的数据不同 自行创建 loginUser
|
// 此处可根据登录用户的数据不同 自行创建 loginUser
|
||||||
LoginUser loginUser = buildLoginUser(user);
|
LoginUser loginUser = buildLoginUser(user);
|
||||||
// 生成token
|
// 生成token
|
||||||
LoginHelper.loginByDevice(loginUser, DeviceType.PC);
|
LoginHelper.loginByDevice(loginUser, DeviceType.PC);
|
||||||
|
|
||||||
recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
recordLogininfor(loginUser.getTenantId(), username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
||||||
recordLoginInfo(user.getUserId());
|
recordLoginInfo(user.getUserId());
|
||||||
return StpUtil.getTokenValue();
|
return StpUtil.getTokenValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String smsLogin(String phonenumber, String smsCode) {
|
public String smsLogin(String tenantId, String phonenumber, String smsCode) {
|
||||||
|
// 校验租户
|
||||||
|
checkTenant(tenantId);
|
||||||
// 通过手机号查找用户
|
// 通过手机号查找用户
|
||||||
SysUserVo user = loadUserByPhonenumber(phonenumber);
|
SysUserVo user = loadUserByPhonenumber(tenantId, phonenumber);
|
||||||
|
|
||||||
checkLogin(LoginType.SMS, user.getUserName(), () -> !validateSmsCode(phonenumber, smsCode));
|
checkLogin(LoginType.SMS, tenantId, user.getUserName(), () -> !validateSmsCode(tenantId, phonenumber, smsCode));
|
||||||
// 此处可根据登录用户的数据不同 自行创建 loginUser
|
// 此处可根据登录用户的数据不同 自行创建 loginUser
|
||||||
LoginUser loginUser = buildLoginUser(user);
|
LoginUser loginUser = buildLoginUser(user);
|
||||||
// 生成token
|
// 生成token
|
||||||
LoginHelper.loginByDevice(loginUser, DeviceType.APP);
|
LoginHelper.loginByDevice(loginUser, DeviceType.APP);
|
||||||
|
|
||||||
recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
||||||
recordLoginInfo(user.getUserId());
|
recordLoginInfo(user.getUserId());
|
||||||
return StpUtil.getTokenValue();
|
return StpUtil.getTokenValue();
|
||||||
}
|
}
|
||||||
@ -106,9 +120,12 @@ public class SysLoginService {
|
|||||||
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
|
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
|
||||||
String openid = "";
|
String openid = "";
|
||||||
SysUserVo user = loadUserByOpenid(openid);
|
SysUserVo user = loadUserByOpenid(openid);
|
||||||
|
// 校验租户
|
||||||
|
checkTenant(user.getTenantId());
|
||||||
|
|
||||||
// 此处可根据登录用户的数据不同 自行创建 loginUser
|
// 此处可根据登录用户的数据不同 自行创建 loginUser
|
||||||
XcxLoginUser loginUser = new XcxLoginUser();
|
XcxLoginUser loginUser = new XcxLoginUser();
|
||||||
|
loginUser.setTenantId(user.getTenantId());
|
||||||
loginUser.setUserId(user.getUserId());
|
loginUser.setUserId(user.getUserId());
|
||||||
loginUser.setUsername(user.getUserName());
|
loginUser.setUsername(user.getUserName());
|
||||||
loginUser.setUserType(user.getUserType());
|
loginUser.setUserType(user.getUserType());
|
||||||
@ -116,7 +133,7 @@ public class SysLoginService {
|
|||||||
// 生成token
|
// 生成token
|
||||||
LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
|
LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
|
||||||
|
|
||||||
recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
||||||
recordLoginInfo(user.getUserId());
|
recordLoginInfo(user.getUserId());
|
||||||
return StpUtil.getTokenValue();
|
return StpUtil.getTokenValue();
|
||||||
}
|
}
|
||||||
@ -128,7 +145,7 @@ public class SysLoginService {
|
|||||||
try {
|
try {
|
||||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||||
StpUtil.logout();
|
StpUtil.logout();
|
||||||
recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
|
recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
|
||||||
} catch (NotLoginException ignored) {
|
} catch (NotLoginException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,13 +153,15 @@ public class SysLoginService {
|
|||||||
/**
|
/**
|
||||||
* 记录登录信息
|
* 记录登录信息
|
||||||
*
|
*
|
||||||
|
* @param tenantId 租户ID
|
||||||
* @param username 用户名
|
* @param username 用户名
|
||||||
* @param status 状态
|
* @param status 状态
|
||||||
* @param message 消息内容
|
* @param message 消息内容
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private void recordLogininfor(String username, String status, String message) {
|
private void recordLogininfor(String tenantId, String username, String status, String message) {
|
||||||
LogininforEvent logininforEvent = new LogininforEvent();
|
LogininforEvent logininforEvent = new LogininforEvent();
|
||||||
|
logininforEvent.setTenantId(tenantId);
|
||||||
logininforEvent.setUsername(username);
|
logininforEvent.setUsername(username);
|
||||||
logininforEvent.setStatus(status);
|
logininforEvent.setStatus(status);
|
||||||
logininforEvent.setMessage(message);
|
logininforEvent.setMessage(message);
|
||||||
@ -153,10 +172,10 @@ public class SysLoginService {
|
|||||||
/**
|
/**
|
||||||
* 校验短信验证码
|
* 校验短信验证码
|
||||||
*/
|
*/
|
||||||
private boolean validateSmsCode(String phonenumber, String smsCode) {
|
private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) {
|
||||||
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber);
|
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber);
|
||||||
if (StringUtils.isBlank(code)) {
|
if (StringUtils.isBlank(code)) {
|
||||||
recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
return code.equals(smsCode);
|
return code.equals(smsCode);
|
||||||
@ -169,23 +188,24 @@ public class SysLoginService {
|
|||||||
* @param code 验证码
|
* @param code 验证码
|
||||||
* @param uuid 唯一标识
|
* @param uuid 唯一标识
|
||||||
*/
|
*/
|
||||||
public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
|
public void validateCaptcha(String tenantId, String username, String code, String uuid, HttpServletRequest request) {
|
||||||
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
|
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
|
||||||
String captcha = RedisUtils.getCacheObject(verifyKey);
|
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||||
RedisUtils.deleteObject(verifyKey);
|
RedisUtils.deleteObject(verifyKey);
|
||||||
if (captcha == null) {
|
if (captcha == null) {
|
||||||
recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
if (!code.equalsIgnoreCase(captcha)) {
|
if (!code.equalsIgnoreCase(captcha)) {
|
||||||
recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
|
recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
|
||||||
throw new CaptchaException();
|
throw new CaptchaException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SysUserVo loadUserByUsername(String username) {
|
private SysUserVo loadUserByUsername(String tenantId, String username) {
|
||||||
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
|
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
|
||||||
.select(SysUser::getUserName, SysUser::getStatus)
|
.select(SysUser::getUserName, SysUser::getStatus)
|
||||||
|
.eq(tenantEnable, SysUser::getTenantId, tenantId)
|
||||||
.eq(SysUser::getUserName, username));
|
.eq(SysUser::getUserName, username));
|
||||||
if (ObjectUtil.isNull(user)) {
|
if (ObjectUtil.isNull(user)) {
|
||||||
log.info("登录用户:{} 不存在.", username);
|
log.info("登录用户:{} 不存在.", username);
|
||||||
@ -197,9 +217,10 @@ public class SysLoginService {
|
|||||||
return userMapper.selectUserByUserName(username);
|
return userMapper.selectUserByUserName(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SysUserVo loadUserByPhonenumber(String phonenumber) {
|
private SysUserVo loadUserByPhonenumber(String tenantId, String phonenumber) {
|
||||||
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
|
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
|
||||||
.select(SysUser::getPhonenumber, SysUser::getStatus)
|
.select(SysUser::getPhonenumber, SysUser::getStatus)
|
||||||
|
.eq(tenantEnable, SysUser::getTenantId, tenantId)
|
||||||
.eq(SysUser::getPhonenumber, phonenumber));
|
.eq(SysUser::getPhonenumber, phonenumber));
|
||||||
if (ObjectUtil.isNull(user)) {
|
if (ObjectUtil.isNull(user)) {
|
||||||
log.info("登录用户:{} 不存在.", phonenumber);
|
log.info("登录用户:{} 不存在.", phonenumber);
|
||||||
@ -230,6 +251,7 @@ public class SysLoginService {
|
|||||||
*/
|
*/
|
||||||
private LoginUser buildLoginUser(SysUserVo user) {
|
private LoginUser buildLoginUser(SysUserVo user) {
|
||||||
LoginUser loginUser = new LoginUser();
|
LoginUser loginUser = new LoginUser();
|
||||||
|
loginUser.setTenantId(user.getTenantId());
|
||||||
loginUser.setUserId(user.getUserId());
|
loginUser.setUserId(user.getUserId());
|
||||||
loginUser.setDeptId(user.getDeptId());
|
loginUser.setDeptId(user.getDeptId());
|
||||||
loginUser.setUsername(user.getUserName());
|
loginUser.setUsername(user.getUserName());
|
||||||
@ -259,7 +281,7 @@ public class SysLoginService {
|
|||||||
/**
|
/**
|
||||||
* 登录校验
|
* 登录校验
|
||||||
*/
|
*/
|
||||||
private void checkLogin(LoginType loginType, String username, Supplier<Boolean> supplier) {
|
private void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) {
|
||||||
String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
|
String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
|
||||||
String loginFail = Constants.LOGIN_FAIL;
|
String loginFail = Constants.LOGIN_FAIL;
|
||||||
|
|
||||||
@ -267,7 +289,7 @@ public class SysLoginService {
|
|||||||
Integer errorNumber = RedisUtils.getCacheObject(errorKey);
|
Integer errorNumber = RedisUtils.getCacheObject(errorKey);
|
||||||
// 锁定时间内登录 则踢出
|
// 锁定时间内登录 则踢出
|
||||||
if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
|
if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
|
||||||
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
||||||
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,12 +299,12 @@ public class SysLoginService {
|
|||||||
// 达到规定错误次数 则锁定登录
|
// 达到规定错误次数 则锁定登录
|
||||||
if (errorNumber.equals(maxRetryCount)) {
|
if (errorNumber.equals(maxRetryCount)) {
|
||||||
RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
|
RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
|
||||||
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
||||||
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
||||||
} else {
|
} else {
|
||||||
// 未达到规定错误次数 则递增
|
// 未达到规定错误次数 则递增
|
||||||
RedisUtils.setCacheObject(errorKey, errorNumber);
|
RedisUtils.setCacheObject(errorKey, errorNumber);
|
||||||
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
|
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
|
||||||
throw new UserException(loginType.getRetryLimitCount(), errorNumber);
|
throw new UserException(loginType.getRetryLimitCount(), errorNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,4 +312,22 @@ public class SysLoginService {
|
|||||||
// 登录成功 清空错误次数
|
// 登录成功 清空错误次数
|
||||||
RedisUtils.deleteObject(errorKey);
|
RedisUtils.deleteObject(errorKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkTenant(String tenantId) {
|
||||||
|
if (tenantEnable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SysTenantVo tenant = tenantService.queryByTenantId(tenantId);
|
||||||
|
if (ObjectUtil.isNull(tenant)) {
|
||||||
|
log.info("登录租户:{} 不存在.", tenantId);
|
||||||
|
throw new TenantException("tenant.not.exists");
|
||||||
|
} else if (TenantStatus.DISABLE.getCode().equals(tenant.getStatus())) {
|
||||||
|
log.info("登录租户:{} 已被停用.", tenantId);
|
||||||
|
throw new TenantException("tenant.blocked");
|
||||||
|
} else if (tenant.getExpireTime() != null && new Date().after(tenant.getExpireTime())) {
|
||||||
|
log.info("登录租户:{} 已超过有效期.", tenantId);
|
||||||
|
throw new TenantException("tenant.expired");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ public class SysRegisterService {
|
|||||||
*/
|
*/
|
||||||
public void register(RegisterBody registerBody) {
|
public void register(RegisterBody registerBody) {
|
||||||
HttpServletRequest request = ServletUtils.getRequest();
|
HttpServletRequest request = ServletUtils.getRequest();
|
||||||
|
String tenantId = registerBody.getTenantId();
|
||||||
String username = registerBody.getUsername();
|
String username = registerBody.getUsername();
|
||||||
String password = registerBody.getPassword();
|
String password = registerBody.getPassword();
|
||||||
// 校验用户类型是否存在
|
// 校验用户类型是否存在
|
||||||
@ -47,9 +48,10 @@ public class SysRegisterService {
|
|||||||
boolean captchaEnabled = configService.selectCaptchaEnabled();
|
boolean captchaEnabled = configService.selectCaptchaEnabled();
|
||||||
// 验证码开关
|
// 验证码开关
|
||||||
if (captchaEnabled) {
|
if (captchaEnabled) {
|
||||||
validateCaptcha(username, registerBody.getCode(), registerBody.getUuid(), request);
|
validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid(), request);
|
||||||
}
|
}
|
||||||
SysUserBo sysUser = new SysUserBo();
|
SysUserBo sysUser = new SysUserBo();
|
||||||
|
sysUser.setTenantId(tenantId);
|
||||||
sysUser.setUserName(username);
|
sysUser.setUserName(username);
|
||||||
sysUser.setNickName(username);
|
sysUser.setNickName(username);
|
||||||
sysUser.setPassword(BCrypt.hashpw(password));
|
sysUser.setPassword(BCrypt.hashpw(password));
|
||||||
@ -62,7 +64,7 @@ public class SysRegisterService {
|
|||||||
if (!regFlag) {
|
if (!regFlag) {
|
||||||
throw new UserException("user.register.error");
|
throw new UserException("user.register.error");
|
||||||
}
|
}
|
||||||
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"));
|
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,16 +75,16 @@ public class SysRegisterService {
|
|||||||
* @param uuid 唯一标识
|
* @param uuid 唯一标识
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
|
public void validateCaptcha(String tenantId, String username, String code, String uuid, HttpServletRequest request) {
|
||||||
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
|
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
|
||||||
String captcha = RedisUtils.getCacheObject(verifyKey);
|
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||||
RedisUtils.deleteObject(verifyKey);
|
RedisUtils.deleteObject(verifyKey);
|
||||||
if (captcha == null) {
|
if (captcha == null) {
|
||||||
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
|
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
if (!code.equalsIgnoreCase(captcha)) {
|
if (!code.equalsIgnoreCase(captcha)) {
|
||||||
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
|
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
|
||||||
throw new CaptchaException();
|
throw new CaptchaException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,13 +92,15 @@ public class SysRegisterService {
|
|||||||
/**
|
/**
|
||||||
* 记录登录信息
|
* 记录登录信息
|
||||||
*
|
*
|
||||||
|
* @param tenantId 租户ID
|
||||||
* @param username 用户名
|
* @param username 用户名
|
||||||
* @param status 状态
|
* @param status 状态
|
||||||
* @param message 消息内容
|
* @param message 消息内容
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private void recordLogininfor(String username, String status, String message) {
|
private void recordLogininfor(String tenantId, String username, String status, String message) {
|
||||||
LogininforEvent logininforEvent = new LogininforEvent();
|
LogininforEvent logininforEvent = new LogininforEvent();
|
||||||
|
logininforEvent.setTenantId(tenantId);
|
||||||
logininforEvent.setUsername(username);
|
logininforEvent.setUsername(username);
|
||||||
logininforEvent.setStatus(status);
|
logininforEvent.setStatus(status);
|
||||||
logininforEvent.setMessage(message);
|
logininforEvent.setMessage(message);
|
||||||
|
|||||||
@ -136,6 +136,21 @@ security:
|
|||||||
- /actuator
|
- /actuator
|
||||||
- /actuator/**
|
- /actuator/**
|
||||||
|
|
||||||
|
# 多租户配置
|
||||||
|
tenant:
|
||||||
|
# 是否开启
|
||||||
|
enable: true
|
||||||
|
# 排除表
|
||||||
|
excludes:
|
||||||
|
- sys_menu
|
||||||
|
- sys_config
|
||||||
|
- sys_dict_type
|
||||||
|
- sys_dict_data
|
||||||
|
- sys_role_dept
|
||||||
|
- sys_role_menu
|
||||||
|
- sys_user_post
|
||||||
|
- sys_user_role
|
||||||
|
|
||||||
# MyBatisPlus配置
|
# MyBatisPlus配置
|
||||||
# https://baomidou.com/config/
|
# https://baomidou.com/config/
|
||||||
mybatis-plus:
|
mybatis-plus:
|
||||||
|
|||||||
@ -43,3 +43,8 @@ sms.code.not.blank=短信验证码不能为空
|
|||||||
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
||||||
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
|
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
|
||||||
xcx.code.not.blank=小程序code不能为空
|
xcx.code.not.blank=小程序code不能为空
|
||||||
|
##租户
|
||||||
|
tenant.number.not.blank=租户编号不能为空
|
||||||
|
tenant.not.exists=对不起, 您的租户不存在,请联系管理员
|
||||||
|
tenant.blocked=对不起,您的租户已禁用,请联系管理员
|
||||||
|
tenant.expired=对不起,您的租户已过期,请联系管理员
|
||||||
|
|||||||
@ -43,3 +43,8 @@ sms.code.not.blank=Sms code cannot be blank
|
|||||||
sms.code.retry.limit.count=Sms code input error {0} times
|
sms.code.retry.limit.count=Sms code input error {0} times
|
||||||
sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {1} minutes
|
sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {1} minutes
|
||||||
xcx.code.not.blank=Mini program code cannot be blank
|
xcx.code.not.blank=Mini program code cannot be blank
|
||||||
|
##租户
|
||||||
|
tenant.number.not.blank=Tenant number cannot be blank
|
||||||
|
tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator
|
||||||
|
tenant.blocked=Sorry, your tenant is disabled. Please contact the administrator
|
||||||
|
tenant.expired=Sorry, your tenant has expired. Please contact the administrator.
|
||||||
|
|||||||
@ -43,3 +43,8 @@ sms.code.not.blank=短信验证码不能为空
|
|||||||
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
||||||
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
|
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
|
||||||
xcx.code.not.blank=小程序code不能为空
|
xcx.code.not.blank=小程序code不能为空
|
||||||
|
##租户
|
||||||
|
tenant.number.not.blank=租户编号不能为空
|
||||||
|
tenant.not.exists=对不起, 您的租户不存在,请联系管理员
|
||||||
|
tenant.blocked=对不起,您的租户已禁用,请联系管理员
|
||||||
|
tenant.expired=对不起,您的租户已过期,请联系管理员
|
||||||
|
|||||||
@ -15,6 +15,12 @@ import jakarta.validation.constraints.NotBlank;
|
|||||||
@Data
|
@Data
|
||||||
public class LoginBody {
|
public class LoginBody {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{tenant.number.not.blank}")
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户名
|
* 用户名
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -22,6 +22,11 @@ public class LoginUser implements Serializable {
|
|||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户ID
|
* 用户ID
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -13,6 +13,12 @@ import jakarta.validation.constraints.NotBlank;
|
|||||||
@Data
|
@Data
|
||||||
public class SmsLoginBody {
|
public class SmsLoginBody {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{tenant.number.not.blank}")
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户名
|
* 用户名
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.ruoyi.common.core.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户状态
|
||||||
|
*
|
||||||
|
* @author LionLi
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum TenantStatus {
|
||||||
|
/**
|
||||||
|
* 正常
|
||||||
|
*/
|
||||||
|
OK("0", "正常"),
|
||||||
|
/**
|
||||||
|
* 停用
|
||||||
|
*/
|
||||||
|
DISABLE("1", "停用"),
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
DELETED("2", "删除");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String info;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package com.ruoyi.common.core.exception;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.exception.base.BaseException;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户信息异常类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class TenantException extends BaseException {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public TenantException(String code, Object... args) {
|
||||||
|
super("tenant", code, args, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -67,6 +67,7 @@ public class LogAspect {
|
|||||||
|
|
||||||
// *========数据库日志=========*//
|
// *========数据库日志=========*//
|
||||||
OperLogEvent operLog = new OperLogEvent();
|
OperLogEvent operLog = new OperLogEvent();
|
||||||
|
operLog.setTenantId(LoginHelper.getTenantId());
|
||||||
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
||||||
// 请求的地址
|
// 请求的地址
|
||||||
String ip = ServletUtils.getClientIP();
|
String ip = ServletUtils.getClientIP();
|
||||||
|
|||||||
@ -19,6 +19,11 @@ public class LogininforEvent implements Serializable {
|
|||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户账号
|
* 用户账号
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -23,6 +23,11 @@ public class OperLogEvent implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private Long operId;
|
private Long operId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 操作模块
|
* 操作模块
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -7,10 +7,14 @@ import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||||
import com.ruoyi.common.mybatis.handler.InjectionMetaObjectHandler;
|
import com.ruoyi.common.mybatis.handler.InjectionMetaObjectHandler;
|
||||||
|
import com.ruoyi.common.mybatis.handler.PlusTenantLineHandler;
|
||||||
import com.ruoyi.common.mybatis.interceptor.PlusDataPermissionInterceptor;
|
import com.ruoyi.common.mybatis.interceptor.PlusDataPermissionInterceptor;
|
||||||
|
import com.ruoyi.common.mybatis.properties.TenantProperties;
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
@ -19,14 +23,19 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
@EnableConfigurationProperties(TenantProperties.class)
|
||||||
@EnableTransactionManagement(proxyTargetClass = true)
|
@EnableTransactionManagement(proxyTargetClass = true)
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@MapperScan("${mybatis-plus.mapperPackage}")
|
@MapperScan("${mybatis-plus.mapperPackage}")
|
||||||
public class MybatisPlusConfig {
|
public class MybatisPlusConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
public MybatisPlusInterceptor mybatisPlusInterceptor(TenantProperties tenantProperties) {
|
||||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||||
|
if (tenantProperties.getEnable()) {
|
||||||
|
// 多租户插件
|
||||||
|
interceptor.addInnerInterceptor(tenantLineInnerInterceptor(tenantProperties));
|
||||||
|
}
|
||||||
// 数据权限处理
|
// 数据权限处理
|
||||||
interceptor.addInnerInterceptor(dataPermissionInterceptor());
|
interceptor.addInnerInterceptor(dataPermissionInterceptor());
|
||||||
// 分页插件
|
// 分页插件
|
||||||
@ -36,6 +45,13 @@ public class MybatisPlusConfig {
|
|||||||
return interceptor;
|
return interceptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多租户插件
|
||||||
|
*/
|
||||||
|
public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) {
|
||||||
|
return new TenantLineInnerInterceptor(new PlusTenantLineHandler(tenantProperties));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据权限拦截器
|
* 数据权限拦截器
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -15,6 +15,6 @@ public class TenantEntity extends BaseEntity {
|
|||||||
/**
|
/**
|
||||||
* 租户编号
|
* 租户编号
|
||||||
*/
|
*/
|
||||||
private String tenantId = "000000";
|
private String tenantId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,54 @@
|
|||||||
|
package com.ruoyi.common.mybatis.handler;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.mybatis.properties.TenantProperties;
|
||||||
|
import com.ruoyi.common.satoken.utils.LoginHelper;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import net.sf.jsqlparser.expression.Expression;
|
||||||
|
import net.sf.jsqlparser.expression.LongValue;
|
||||||
|
import net.sf.jsqlparser.expression.NullValue;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义租户处理器
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PlusTenantLineHandler implements TenantLineHandler {
|
||||||
|
|
||||||
|
private final TenantProperties tenantProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Expression getTenantId() {
|
||||||
|
String tenantId = LoginHelper.getTenantId();
|
||||||
|
if (StringUtils.isNotBlank(tenantId)) {
|
||||||
|
//多租户模式,租户id从当前用户获取
|
||||||
|
return new LongValue(tenantId);
|
||||||
|
}
|
||||||
|
return new NullValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean ignoreTable(String tableName) {
|
||||||
|
String tenantId = LoginHelper.getTenantId();
|
||||||
|
// 判断是否有租户
|
||||||
|
if (StringUtils.isNotBlank(tenantId)) {
|
||||||
|
// 判断是否平台超级管理员,如果是平台超级管理员则拥有所有数据权限
|
||||||
|
if (!LoginHelper.isAdmin()) {
|
||||||
|
// 不需要过滤租户的表
|
||||||
|
List<String> excludes = tenantProperties.getExcludes();
|
||||||
|
// 非业务表
|
||||||
|
excludes.addAll(List.of(
|
||||||
|
"gen_table",
|
||||||
|
"gen_table_column"
|
||||||
|
));
|
||||||
|
return excludes.contains(tableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package com.ruoyi.common.mybatis.properties;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户 配置属性
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ConfigurationProperties(prefix = "tenant")
|
||||||
|
public class TenantProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用
|
||||||
|
*/
|
||||||
|
private Boolean enable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排除表
|
||||||
|
*/
|
||||||
|
private List<String> excludes;
|
||||||
|
|
||||||
|
}
|
||||||
@ -96,6 +96,19 @@ public class LoginHelper {
|
|||||||
return loginUser.getUserId();
|
return loginUser.getUserId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取租户ID
|
||||||
|
*/
|
||||||
|
public static String getTenantId() {
|
||||||
|
LoginUser loginUser;
|
||||||
|
try {
|
||||||
|
loginUser = getLoginUser();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return loginUser.getTenantId();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取部门ID
|
* 获取部门ID
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -23,7 +23,7 @@ public class SysLogininforBo {
|
|||||||
/**
|
/**
|
||||||
* 租户编号
|
* 租户编号
|
||||||
*/
|
*/
|
||||||
private String tenantId = "000000";
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户账号
|
* 用户账号
|
||||||
|
|||||||
@ -25,7 +25,7 @@ public class SysOperLogBo {
|
|||||||
/**
|
/**
|
||||||
* 租户编号
|
* 租户编号
|
||||||
*/
|
*/
|
||||||
private String tenantId = "000000";
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模块标题
|
* 模块标题
|
||||||
|
|||||||
@ -27,6 +27,11 @@ public class SysUserVo implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门ID
|
* 部门ID
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.ruoyi.system.runner;
|
package com.ruoyi.system.runner;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
|
||||||
|
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
|
||||||
import com.ruoyi.common.core.config.RuoYiConfig;
|
import com.ruoyi.common.core.config.RuoYiConfig;
|
||||||
import com.ruoyi.system.service.ISysConfigService;
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
import com.ruoyi.system.service.ISysDictTypeService;
|
import com.ruoyi.system.service.ISysDictTypeService;
|
||||||
@ -27,15 +29,18 @@ public class SystemApplicationRunner implements ApplicationRunner {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments args) throws Exception {
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
|
InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build());
|
||||||
ossConfigService.init();
|
ossConfigService.init();
|
||||||
log.info("初始化OSS配置成功");
|
log.info("初始化OSS配置成功");
|
||||||
if (ruoyiConfig.isCacheLazy()) {
|
if (ruoyiConfig.isCacheLazy()) {
|
||||||
|
InterceptorIgnoreHelper.clearIgnoreStrategy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
configService.loadingConfigCache();
|
configService.loadingConfigCache();
|
||||||
log.info("加载参数缓存数据成功");
|
log.info("加载参数缓存数据成功");
|
||||||
dictTypeService.loadingDictCache();
|
dictTypeService.loadingDictCache();
|
||||||
log.info("加载字典缓存数据成功");
|
log.info("加载字典缓存数据成功");
|
||||||
|
InterceptorIgnoreHelper.clearIgnoreStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,11 @@ public interface ISysTenantService {
|
|||||||
*/
|
*/
|
||||||
SysTenantVo queryById(Long id);
|
SysTenantVo queryById(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于租户ID查询租户
|
||||||
|
*/
|
||||||
|
SysTenantVo queryByTenantId(String tenantId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询租户列表
|
* 查询租户列表
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -68,6 +68,7 @@ public class SysLogininforServiceImpl implements ISysLogininforService {
|
|||||||
String browser = userAgent.getBrowser().getName();
|
String browser = userAgent.getBrowser().getName();
|
||||||
// 封装对象
|
// 封装对象
|
||||||
SysLogininforBo logininfor = new SysLogininforBo();
|
SysLogininforBo logininfor = new SysLogininforBo();
|
||||||
|
logininfor.setTenantId(logininforEvent.getTenantId());
|
||||||
logininfor.setUserName(logininforEvent.getUsername());
|
logininfor.setUserName(logininforEvent.getUsername());
|
||||||
logininfor.setIpaddr(ip);
|
logininfor.setIpaddr(ip);
|
||||||
logininfor.setLoginLocation(address);
|
logininfor.setLoginLocation(address);
|
||||||
|
|||||||
@ -53,6 +53,11 @@ public class SysTenantServiceImpl implements ISysTenantService {
|
|||||||
return baseMapper.selectVoById(id);
|
return baseMapper.selectVoById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SysTenantVo queryByTenantId(String tenantId) {
|
||||||
|
return baseMapper.selectVoOne(new LambdaQueryWrapper<SysTenant>().eq(SysTenant::getTenantId, tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询租户列表
|
* 查询租户列表
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
<sql id="selectUserVo">
|
<sql id="selectUserVo">
|
||||||
select u.user_id,
|
select u.user_id,
|
||||||
|
u.tenant_id,
|
||||||
u.dept_id,
|
u.dept_id,
|
||||||
u.user_name,
|
u.user_name,
|
||||||
u.nick_name,
|
u.nick_name,
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 登录方法
|
// 登录方法
|
||||||
export function login(username, password, code, uuid) {
|
export function login(tenantId, username, password, code, uuid) {
|
||||||
const data = {
|
const data = {
|
||||||
|
tenantId,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
code,
|
code,
|
||||||
|
|||||||
@ -31,12 +31,13 @@ const user = {
|
|||||||
actions: {
|
actions: {
|
||||||
// 登录
|
// 登录
|
||||||
Login({ commit }, userInfo) {
|
Login({ commit }, userInfo) {
|
||||||
|
const tenantId = userInfo.tenantId.trim()
|
||||||
const username = userInfo.username.trim()
|
const username = userInfo.username.trim()
|
||||||
const password = userInfo.password
|
const password = userInfo.password
|
||||||
const code = userInfo.code
|
const code = userInfo.code
|
||||||
const uuid = userInfo.uuid
|
const uuid = userInfo.uuid
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
login(username, password, code, uuid).then(res => {
|
login(tenantId, username, password, code, uuid).then(res => {
|
||||||
setToken(res.data.token)
|
setToken(res.data.token)
|
||||||
commit('SET_TOKEN', res.data.token)
|
commit('SET_TOKEN', res.data.token)
|
||||||
resolve()
|
resolve()
|
||||||
|
|||||||
@ -2,6 +2,16 @@
|
|||||||
<div class="login">
|
<div class="login">
|
||||||
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
|
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
|
||||||
<h3 class="title">RuoYi-Vue-Plus后台管理系统</h3>
|
<h3 class="title">RuoYi-Vue-Plus后台管理系统</h3>
|
||||||
|
<el-form-item prop="tenantId">
|
||||||
|
<el-input
|
||||||
|
v-model="loginForm.tenantId"
|
||||||
|
type="text"
|
||||||
|
auto-complete="off"
|
||||||
|
placeholder="租户编号"
|
||||||
|
>
|
||||||
|
<svg-icon slot="prefix" icon-class="input" class="el-input__icon input-icon" />
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item prop="username">
|
<el-form-item prop="username">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="loginForm.username"
|
v-model="loginForm.username"
|
||||||
@ -72,6 +82,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
codeUrl: "",
|
codeUrl: "",
|
||||||
loginForm: {
|
loginForm: {
|
||||||
|
tenantId: "000000",
|
||||||
username: "admin",
|
username: "admin",
|
||||||
password: "admin123",
|
password: "admin123",
|
||||||
rememberMe: false,
|
rememberMe: false,
|
||||||
@ -79,6 +90,9 @@ export default {
|
|||||||
uuid: ""
|
uuid: ""
|
||||||
},
|
},
|
||||||
loginRules: {
|
loginRules: {
|
||||||
|
tenantId: [
|
||||||
|
{ required: true, trigger: "blur", message: "请输入您的租户编号" }
|
||||||
|
],
|
||||||
username: [
|
username: [
|
||||||
{ required: true, trigger: "blur", message: "请输入您的账号" }
|
{ required: true, trigger: "blur", message: "请输入您的账号" }
|
||||||
],
|
],
|
||||||
@ -118,10 +132,12 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
getCookie() {
|
getCookie() {
|
||||||
|
const tenantId = Cookies.get("tenantId");
|
||||||
const username = Cookies.get("username");
|
const username = Cookies.get("username");
|
||||||
const password = Cookies.get("password");
|
const password = Cookies.get("password");
|
||||||
const rememberMe = Cookies.get('rememberMe')
|
const rememberMe = Cookies.get('rememberMe')
|
||||||
this.loginForm = {
|
this.loginForm = {
|
||||||
|
tenantId: tenantId === undefined ? this.loginForm.tenantId : tenantId,
|
||||||
username: username === undefined ? this.loginForm.username : username,
|
username: username === undefined ? this.loginForm.username : username,
|
||||||
password: password === undefined ? this.loginForm.password : decrypt(password),
|
password: password === undefined ? this.loginForm.password : decrypt(password),
|
||||||
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
|
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
|
||||||
@ -132,10 +148,12 @@ export default {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
if (this.loginForm.rememberMe) {
|
if (this.loginForm.rememberMe) {
|
||||||
|
Cookies.set("tenantId", this.loginForm.tenantId, { expires: 30 });
|
||||||
Cookies.set("username", this.loginForm.username, { expires: 30 });
|
Cookies.set("username", this.loginForm.username, { expires: 30 });
|
||||||
Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
|
Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
|
||||||
Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
|
Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
|
||||||
} else {
|
} else {
|
||||||
|
Cookies.remove("tenantId");
|
||||||
Cookies.remove("username");
|
Cookies.remove("username");
|
||||||
Cookies.remove("password");
|
Cookies.remove("password");
|
||||||
Cookies.remove('rememberMe');
|
Cookies.remove('rememberMe');
|
||||||
|
|||||||
@ -2,6 +2,16 @@
|
|||||||
<div class="register">
|
<div class="register">
|
||||||
<el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form">
|
<el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form">
|
||||||
<h3 class="title">RuoYi-Vue-Plus后台管理系统</h3>
|
<h3 class="title">RuoYi-Vue-Plus后台管理系统</h3>
|
||||||
|
<el-form-item prop="tenantId">
|
||||||
|
<el-input
|
||||||
|
v-model="loginForm.tenantId"
|
||||||
|
type="text"
|
||||||
|
auto-complete="off"
|
||||||
|
placeholder="租户编号"
|
||||||
|
>
|
||||||
|
<svg-icon slot="prefix" icon-class="input" class="el-input__icon input-icon" />
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item prop="username">
|
<el-form-item prop="username">
|
||||||
<el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="账号">
|
<el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="账号">
|
||||||
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
|
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
|
||||||
@ -82,6 +92,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
codeUrl: "",
|
codeUrl: "",
|
||||||
registerForm: {
|
registerForm: {
|
||||||
|
tenantId: "",
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
confirmPassword: "",
|
confirmPassword: "",
|
||||||
@ -90,6 +101,9 @@ export default {
|
|||||||
userType: "sys_user"
|
userType: "sys_user"
|
||||||
},
|
},
|
||||||
registerRules: {
|
registerRules: {
|
||||||
|
tenantId: [
|
||||||
|
{ required: true, trigger: "blur", message: "请输入您的租户编号" }
|
||||||
|
],
|
||||||
username: [
|
username: [
|
||||||
{ required: true, trigger: "blur", message: "请输入您的账号" },
|
{ required: true, trigger: "blur", message: "请输入您的账号" },
|
||||||
{ min: 2, max: 20, message: '用户账号长度必须介于 2 和 20 之间', trigger: 'blur' }
|
{ min: 2, max: 20, message: '用户账号长度必须介于 2 和 20 之间', trigger: 'blur' }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user