🔨 登录使用系统配置.

This commit is contained in:
lijiahang
2025-02-06 09:55:37 +08:00
parent 2d5835b150
commit 6791ea5770

View File

@@ -24,6 +24,7 @@ package org.dromara.visor.module.infra.service.impl;
import cn.orionsec.kit.lang.annotation.Keep; import cn.orionsec.kit.lang.annotation.Keep;
import cn.orionsec.kit.lang.define.wrapper.Pair; import cn.orionsec.kit.lang.define.wrapper.Pair;
import cn.orionsec.kit.lang.utils.Booleans;
import cn.orionsec.kit.lang.utils.Exceptions; import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.Strings; import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.collect.Lists; import cn.orionsec.kit.lang.utils.collect.Lists;
@@ -31,6 +32,8 @@ import cn.orionsec.kit.lang.utils.crypto.Signatures;
import cn.orionsec.kit.lang.utils.time.Dates; import cn.orionsec.kit.lang.utils.time.Dates;
import cn.orionsec.kit.web.servlet.web.Servlets; import cn.orionsec.kit.web.servlet.web.Servlets;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import org.dromara.visor.common.config.ConfigStore;
import org.dromara.visor.common.constant.ConfigKeys;
import org.dromara.visor.common.constant.Const; import org.dromara.visor.common.constant.Const;
import org.dromara.visor.common.constant.ErrorMessage; import org.dromara.visor.common.constant.ErrorMessage;
import org.dromara.visor.common.constant.ExtraFieldConst; import org.dromara.visor.common.constant.ExtraFieldConst;
@@ -48,7 +51,7 @@ import org.dromara.visor.module.infra.convert.SystemUserConvert;
import org.dromara.visor.module.infra.dao.SystemUserDAO; import org.dromara.visor.module.infra.dao.SystemUserDAO;
import org.dromara.visor.module.infra.dao.SystemUserRoleDAO; import org.dromara.visor.module.infra.dao.SystemUserRoleDAO;
import org.dromara.visor.module.infra.define.cache.UserCacheKeyDefine; import org.dromara.visor.module.infra.define.cache.UserCacheKeyDefine;
import org.dromara.visor.module.infra.define.config.AppAuthenticationConfig; import org.dromara.visor.module.infra.define.config.AppLoginConfig;
import org.dromara.visor.module.infra.define.message.SystemUserMessageDefine; import org.dromara.visor.module.infra.define.message.SystemUserMessageDefine;
import org.dromara.visor.module.infra.entity.domain.SystemUserDO; import org.dromara.visor.module.infra.entity.domain.SystemUserDO;
import org.dromara.visor.module.infra.entity.dto.LoginTokenDTO; import org.dromara.visor.module.infra.entity.dto.LoginTokenDTO;
@@ -63,6 +66,7 @@ import org.dromara.visor.module.infra.service.UserPermissionService;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.*; import java.util.*;
@@ -80,7 +84,7 @@ import java.util.stream.Collectors;
public class AuthenticationServiceImpl implements AuthenticationService { public class AuthenticationServiceImpl implements AuthenticationService {
@Resource @Resource
private AppAuthenticationConfig appAuthenticationConfig; private AppLoginConfig appLoginConfig;
@Resource @Resource
private SystemUserDAO systemUserDAO; private SystemUserDAO systemUserDAO;
@@ -98,6 +102,17 @@ public class AuthenticationServiceImpl implements AuthenticationService {
@Resource @Resource
private RedisTemplate<String, String> redisTemplate; private RedisTemplate<String, String> redisTemplate;
@Resource
private ConfigStore configStore;
@PostConstruct
public void initCacheExpireTime() {
// 监听并且设置缓存过期时间
configStore.int32(ConfigKeys.LOGIN_LOGIN_SESSION_TIME).onChange((v, b) -> this.setCacheExpireTime());
configStore.int32(ConfigKeys.LOGIN_REFRESH_INTERVAL).onChange((v, b) -> this.setCacheExpireTime());
this.setCacheExpireTime();
}
@Override @Override
public UserLoginVO login(UserLoginRequest request, HttpServletRequest servletRequest) { public UserLoginVO login(UserLoginRequest request, HttpServletRequest servletRequest) {
// 获取登录信息 // 获取登录信息
@@ -118,7 +133,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
// 用户状态校验 // 用户状态校验
this.checkUserStatus(user); this.checkUserStatus(user);
Long id = user.getId(); Long id = user.getId();
// 设置上次登录时间 // 设置最后登录时间
this.setLastLoginTime(id); this.setLastLoginTime(id);
// 删除用户缓存 // 删除用户缓存
this.deleteUserCache(user); this.deleteUserCache(user);
@@ -126,7 +141,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
this.setUserCache(user); this.setUserCache(user);
long current = System.currentTimeMillis(); long current = System.currentTimeMillis();
// 不允许多端登录 // 不允许多端登录
if (!appAuthenticationConfig.getAllowMultiDevice()) { if (Booleans.isFalse(appLoginConfig.getAllowMultiDevice())) {
// 无效化其他缓存 // 无效化其他缓存
this.invalidOtherDeviceToken(id, current, remoteAddr, location, userAgent); this.invalidOtherDeviceToken(id, current, remoteAddr, location, userAgent);
} }
@@ -188,7 +203,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
return JSON.parseObject(loginCache, LoginTokenDTO.class); return JSON.parseObject(loginCache, LoginTokenDTO.class);
} }
// loginToken 不存在 需要查询 refreshToken // loginToken 不存在 需要查询 refreshToken
if (!appAuthenticationConfig.getAllowRefresh()) { if (Booleans.isFalse(appLoginConfig.getAllowRefresh())) {
return null; return null;
} }
String refreshKey = UserCacheKeyDefine.LOGIN_REFRESH.format(pair.getKey(), pair.getValue()); String refreshKey = UserCacheKeyDefine.LOGIN_REFRESH.format(pair.getKey(), pair.getValue());
@@ -203,7 +218,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
refresh.setRefreshCount(refreshCount); refresh.setRefreshCount(refreshCount);
// 设置登录缓存 // 设置登录缓存
RedisStrings.setJson(loginKey, UserCacheKeyDefine.LOGIN_TOKEN, refresh); RedisStrings.setJson(loginKey, UserCacheKeyDefine.LOGIN_TOKEN, refresh);
if (refreshCount < appAuthenticationConfig.getMaxRefreshCount()) { if (refreshCount < appLoginConfig.getMaxRefreshCount()) {
// 小于续签最大次数 则再次设置 refreshToken // 小于续签最大次数 则再次设置 refreshToken
RedisStrings.setJson(refreshKey, UserCacheKeyDefine.LOGIN_REFRESH, refresh); RedisStrings.setJson(refreshKey, UserCacheKeyDefine.LOGIN_REFRESH, refresh);
} else { } else {
@@ -219,12 +234,14 @@ public class AuthenticationServiceImpl implements AuthenticationService {
if (password.length() != Const.MD5_LEN) { if (password.length() != Const.MD5_LEN) {
throw Exceptions.argument(ErrorMessage.USERNAME_PASSWORD_ERROR); throw Exceptions.argument(ErrorMessage.USERNAME_PASSWORD_ERROR);
} }
// 检查登录失败次数 // 检查登录失败次数锁定
String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(username); if (Booleans.isTrue(appLoginConfig.getLoginFailedLock())) {
String failedCount = redisTemplate.opsForValue().get(failedCountKey); String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(username);
if (failedCount != null String failedCount = redisTemplate.opsForValue().get(failedCountKey);
&& Integer.parseInt(failedCount) >= appAuthenticationConfig.getLoginFailedLockCount()) { if (failedCount != null
throw Exceptions.argument(ErrorMessage.MAX_LOGIN_FAILED); && Integer.parseInt(failedCount) >= appLoginConfig.getLoginFailedLockThreshold()) {
throw Exceptions.argument(ErrorMessage.MAX_LOGIN_FAILED);
}
} }
// 获取登录用户 // 获取登录用户
SystemUserDO user = systemUserDAO.of() SystemUserDO user = systemUserDAO.of()
@@ -244,7 +261,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
// 刷新登录失败缓存 // 刷新登录失败缓存
String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(user.getUsername()); String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(user.getUsername());
redisTemplate.opsForValue().increment(failedCountKey); redisTemplate.opsForValue().increment(failedCountKey);
RedisUtils.setExpire(failedCountKey, appAuthenticationConfig.getLoginFailedLockTime(), TimeUnit.MINUTES); RedisUtils.setExpire(failedCountKey, appLoginConfig.getLoginFailedLockTime(), TimeUnit.MINUTES);
} }
return passRight; return passRight;
} }
@@ -268,13 +285,17 @@ public class AuthenticationServiceImpl implements AuthenticationService {
if (passRight) { if (passRight) {
return; return;
} }
// 检查是否开启登录失败发信
if (!Booleans.isTrue(appLoginConfig.getLoginFailedSend())) {
return;
}
String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(user.getUsername()); String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(user.getUsername());
String failedCountStr = redisTemplate.opsForValue().get(failedCountKey); String failedCountStr = redisTemplate.opsForValue().get(failedCountKey);
if (failedCountStr == null || !Strings.isInteger(failedCountStr)) { if (failedCountStr == null || !Strings.isInteger(failedCountStr)) {
return; return;
} }
// 直接用相等 因为只触发一次 // 直接用相等 因为只触发一次
if (!appAuthenticationConfig.getLoginFailedSendThreshold().equals(Integer.valueOf(failedCountStr))) { if (!Integer.valueOf(failedCountStr).equals(appLoginConfig.getLoginFailedSendThreshold())) {
return; return;
} }
// 发送站内信 // 发送站内信
@@ -393,7 +414,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
} }
} }
// 删除续签信息 // 删除续签信息
if (appAuthenticationConfig.getAllowRefresh()) { if (Booleans.isTrue(appLoginConfig.getAllowRefresh())) {
RedisUtils.scanKeysDelete(UserCacheKeyDefine.LOGIN_REFRESH.format(id, "*")); RedisUtils.scanKeysDelete(UserCacheKeyDefine.LOGIN_REFRESH.format(id, "*"));
} }
} }
@@ -421,7 +442,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
.build(); .build();
RedisStrings.setJson(loginKey, UserCacheKeyDefine.LOGIN_TOKEN, loginValue); RedisStrings.setJson(loginKey, UserCacheKeyDefine.LOGIN_TOKEN, loginValue);
// 生成 refreshToken // 生成 refreshToken
if (appAuthenticationConfig.getAllowRefresh()) { if (Booleans.isTrue(appLoginConfig.getAllowRefresh())) {
String refreshKey = UserCacheKeyDefine.LOGIN_REFRESH.format(id, loginTime); String refreshKey = UserCacheKeyDefine.LOGIN_REFRESH.format(id, loginTime);
RedisStrings.setJson(refreshKey, UserCacheKeyDefine.LOGIN_REFRESH, loginValue); RedisStrings.setJson(refreshKey, UserCacheKeyDefine.LOGIN_REFRESH, loginValue);
} }
@@ -429,4 +450,15 @@ public class AuthenticationServiceImpl implements AuthenticationService {
return AesEncryptUtils.encryptBase62(id + ":" + loginTime); return AesEncryptUtils.encryptBase62(id + ":" + loginTime);
} }
/**
* 重新设置缓存时间
*/
private void setCacheExpireTime() {
Integer loginSessionTime = appLoginConfig.getLoginSessionTime();
if (loginSessionTime != null) {
UserCacheKeyDefine.LOGIN_TOKEN.setTimeout(loginSessionTime);
UserCacheKeyDefine.LOGIN_REFRESH.setTimeout(loginSessionTime + appLoginConfig.getRefreshInterval());
}
}
} }