123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- package org.dromara.web.service;
- import cn.dev33.satoken.exception.NotLoginException;
- import cn.dev33.satoken.stp.StpUtil;
- import cn.hutool.core.bean.BeanUtil;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.lang.Opt;
- import cn.hutool.core.util.ObjectUtil;
- import com.baomidou.lock.annotation.Lock4j;
- import lombok.RequiredArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import me.zhyd.oauth.model.AuthUser;
- import org.dromara.common.core.constant.CacheConstants;
- import org.dromara.common.core.constant.Constants;
- import org.dromara.common.core.constant.SystemConstants;
- import org.dromara.common.core.constant.TenantConstants;
- import org.dromara.common.core.domain.dto.PostDTO;
- import org.dromara.common.core.domain.dto.RoleDTO;
- import org.dromara.common.core.domain.model.LoginUser;
- import org.dromara.common.core.enums.LoginType;
- import org.dromara.common.core.exception.ServiceException;
- import org.dromara.common.core.exception.user.UserException;
- import org.dromara.common.core.utils.*;
- import org.dromara.common.log.event.LogininforEvent;
- import org.dromara.common.mybatis.helper.DataPermissionHelper;
- import org.dromara.common.redis.utils.RedisUtils;
- import org.dromara.common.satoken.utils.LoginHelper;
- import org.dromara.common.tenant.exception.TenantException;
- import org.dromara.common.tenant.helper.TenantHelper;
- import org.dromara.system.domain.SysUser;
- import org.dromara.system.domain.bo.SysSocialBo;
- import org.dromara.system.domain.vo.*;
- import org.dromara.system.mapper.SysUserMapper;
- import org.dromara.system.service.*;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Service;
- import java.time.Duration;
- import java.util.Date;
- import java.util.List;
- import java.util.function.Supplier;
- /**
- * 登录校验方法
- *
- * @author Lion Li
- */
- @RequiredArgsConstructor
- @Slf4j
- @Service
- public class SysLoginService {
- @Value("${user.password.maxRetryCount}")
- private Integer maxRetryCount;
- @Value("${user.password.lockTime}")
- private Integer lockTime;
- private final ISysTenantService tenantService;
- private final ISysPermissionService permissionService;
- private final ISysSocialService sysSocialService;
- private final ISysRoleService roleService;
- private final ISysDeptService deptService;
- private final ISysPostService postService;
- private final SysUserMapper userMapper;
- /**
- * 绑定第三方用户
- *
- * @param authUserData 授权响应实体
- */
- @Lock4j
- public void socialRegister(AuthUser authUserData) {
- String authId = authUserData.getSource() + authUserData.getUuid();
- // 第三方用户信息
- SysSocialBo bo = BeanUtil.toBean(authUserData, SysSocialBo.class);
- BeanUtil.copyProperties(authUserData.getToken(), bo);
- Long userId = LoginHelper.getUserId();
- bo.setUserId(userId);
- bo.setAuthId(authId);
- bo.setOpenId(authUserData.getUuid());
- bo.setUserName(authUserData.getUsername());
- bo.setNickName(authUserData.getNickname());
- List<SysSocialVo> checkList = sysSocialService.selectByAuthId(authId);
- if (CollUtil.isNotEmpty(checkList)) {
- throw new ServiceException("此三方账号已经被绑定!");
- }
- // 查询是否已经绑定用户
- SysSocialBo params = new SysSocialBo();
- params.setUserId(userId);
- params.setSource(bo.getSource());
- List<SysSocialVo> list = sysSocialService.queryList(params);
- if (CollUtil.isEmpty(list)) {
- // 没有绑定用户, 新增用户信息
- sysSocialService.insertByBo(bo);
- } else {
- // 更新用户信息
- bo.setId(list.get(0).getId());
- sysSocialService.updateByBo(bo);
- // 如果要绑定的平台账号已经被绑定过了 是否抛异常自行决断
- // throw new ServiceException("此平台账号已经被绑定!");
- }
- }
- /**
- * 退出登录
- */
- public void logout() {
- try {
- LoginUser loginUser = LoginHelper.getLoginUser();
- if (ObjectUtil.isNull(loginUser)) {
- return;
- }
- if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
- // 超级管理员 登出清除动态租户
- TenantHelper.clearDynamic();
- }
- recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
- } catch (NotLoginException ignored) {
- } finally {
- try {
- StpUtil.logout();
- } catch (NotLoginException ignored) {
- }
- }
- }
- /**
- * 记录登录信息
- *
- * @param tenantId 租户ID
- * @param username 用户名
- * @param status 状态
- * @param message 消息内容
- */
- public void recordLogininfor(String tenantId, String username, String status, String message) {
- LogininforEvent logininforEvent = new LogininforEvent();
- logininforEvent.setTenantId(tenantId);
- logininforEvent.setUsername(username);
- logininforEvent.setStatus(status);
- logininforEvent.setMessage(message);
- logininforEvent.setRequest(ServletUtils.getRequest());
- SpringUtils.context().publishEvent(logininforEvent);
- }
- /**
- * 构建登录用户
- */
- public LoginUser buildLoginUser(SysUserVo user) {
- LoginUser loginUser = new LoginUser();
- Long userId = user.getUserId();
- loginUser.setTenantId(user.getTenantId());
- loginUser.setUserId(userId);
- loginUser.setDeptId(user.getDeptId());
- loginUser.setUsername(user.getUserName());
- loginUser.setNickname(user.getNickName());
- loginUser.setUserType(user.getUserType());
- loginUser.setMenuPermission(permissionService.getMenuPermission(userId));
- loginUser.setRolePermission(permissionService.getRolePermission(userId));
- if (ObjectUtil.isNotNull(user.getDeptId())) {
- Opt<SysDeptVo> deptOpt = Opt.of(user.getDeptId()).map(deptService::selectDeptById);
- loginUser.setDeptName(deptOpt.map(SysDeptVo::getDeptName).orElse(StringUtils.EMPTY));
- loginUser.setDeptCategory(deptOpt.map(SysDeptVo::getDeptCategory).orElse(StringUtils.EMPTY));
- }
- List<SysRoleVo> roles = roleService.selectRolesByUserId(userId);
- List<SysPostVo> posts = postService.selectPostsByUserId(userId);
- loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class));
- loginUser.setPosts(BeanUtil.copyToList(posts, PostDTO.class));
- return loginUser;
- }
- /**
- * 记录登录信息
- *
- * @param userId 用户ID
- */
- public void recordLoginInfo(Long userId, String ip) {
- SysUser sysUser = new SysUser();
- sysUser.setUserId(userId);
- sysUser.setLoginIp(ip);
- sysUser.setLoginDate(DateUtils.getNowDate());
- sysUser.setUpdateBy(userId);
- DataPermissionHelper.ignore(() -> userMapper.updateById(sysUser));
- }
- /**
- * 登录校验
- */
- public void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) {
- String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
- String loginFail = Constants.LOGIN_FAIL;
- // 获取用户登录错误次数,默认为0 (可自定义限制策略 例如: key + username + ip)
- int errorNumber = ObjectUtil.defaultIfNull(RedisUtils.getCacheObject(errorKey), 0);
- // 锁定时间内登录 则踢出
- if (errorNumber >= maxRetryCount) {
- recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
- throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
- }
- if (supplier.get()) {
- // 错误次数递增
- errorNumber++;
- RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
- // 达到规定错误次数 则锁定登录
- if (errorNumber >= maxRetryCount) {
- recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
- throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
- } else {
- // 未达到规定错误次数
- recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
- throw new UserException(loginType.getRetryLimitCount(), errorNumber);
- }
- }
- // 登录成功 清空错误次数
- RedisUtils.deleteObject(errorKey);
- }
- /**
- * 校验租户
- *
- * @param tenantId 租户ID
- */
- public void checkTenant(String tenantId) {
- if (!TenantHelper.isEnable()) {
- return;
- }
- if (StringUtils.isBlank(tenantId)) {
- throw new TenantException("tenant.number.not.blank");
- }
- if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
- return;
- }
- SysTenantVo tenant = tenantService.queryByTenantId(tenantId);
- if (ObjectUtil.isNull(tenant)) {
- log.info("登录租户:{} 不存在.", tenantId);
- throw new TenantException("tenant.not.exists");
- } else if (SystemConstants.DISABLE.equals(tenant.getStatus())) {
- log.info("登录租户:{} 已被停用.", tenantId);
- throw new TenantException("tenant.blocked");
- } else if (ObjectUtil.isNotNull(tenant.getExpireTime())
- && new Date().after(tenant.getExpireTime())) {
- log.info("登录租户:{} 已超过有效期.", tenantId);
- throw new TenantException("tenant.expired");
- }
- }
- }
|