登录配置化.

This commit is contained in:
lijiahang
2024-03-05 19:31:00 +08:00
parent 554c62abf7
commit 93407460d8
12 changed files with 150 additions and 37 deletions

View File

@@ -0,0 +1,44 @@
package com.orion.ops.module.infra.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 应用认证配置
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/3/5 18:26
*/
@Data
@Component
@ConfigurationProperties("app.authentication")
public class AppAuthenticationConfig {
/**
* 是否允许多端登录
*/
private Boolean allowMultiDevice;
/**
* 是否允许凭证续签
*/
private Boolean allowRefresh;
/**
* 凭证续签最大次数
*/
private Integer maxRefreshCount;
/**
* 登录失败锁定次数
*/
private Integer loginFailedLockCount;
/**
* 登录失败锁定时间 (分)
*/
private Integer loginFailedLockTime;
}

View File

@@ -38,7 +38,6 @@ public interface UserCacheKeyDefine {
.desc("用户登录失败次数 ${username}")
.type(Integer.class)
.struct(RedisCacheStruct.STRING)
.timeout(3, TimeUnit.DAYS)
.build();
CacheKeyDefine LOGIN_TOKEN = new CacheKeyBuilder()

View File

@@ -16,16 +16,6 @@ import javax.servlet.http.HttpServletRequest;
*/
public interface AuthenticationService {
// TODO 配置化
// 允许多端登录
boolean allowMultiDevice = true;
// 允许凭证续签
boolean allowRefresh = true;
// 凭证续签最大次数
int maxRefreshCount = 3;
// 失败锁定次数
int maxFailedLoginCount = 5;
/**
* 登录
*

View File

@@ -16,6 +16,7 @@ import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.framework.redis.core.utils.RedisStrings;
import com.orion.ops.framework.redis.core.utils.RedisUtils;
import com.orion.ops.framework.security.core.utils.SecurityUtils;
import com.orion.ops.module.infra.config.AppAuthenticationConfig;
import com.orion.ops.module.infra.convert.SystemUserConvert;
import com.orion.ops.module.infra.dao.SystemUserDAO;
import com.orion.ops.module.infra.dao.SystemUserRoleDAO;
@@ -39,6 +40,7 @@ import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -51,6 +53,9 @@ import java.util.stream.Collectors;
@Service
public class AuthenticationServiceImpl implements AuthenticationService {
@Resource
private AppAuthenticationConfig appAuthenticationConfig;
@Resource
private SystemUserDAO systemUserDAO;
@@ -95,7 +100,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
String userAgent = Servlets.getUserAgent(servletRequest);
long current = System.currentTimeMillis();
// 不允许多端登录
if (!allowMultiDevice) {
if (!appAuthenticationConfig.getAllowMultiDevice()) {
// 无效化其他缓存
this.invalidOtherDeviceToken(user.getId(), current, remoteAddr, location, userAgent);
}
@@ -157,7 +162,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
return JSON.parseObject(loginCache, LoginTokenDTO.class);
}
// loginToken 不存在 需要查询 refreshToken
if (!allowRefresh) {
if (!appAuthenticationConfig.getAllowRefresh()) {
return null;
}
String refreshKey = UserCacheKeyDefine.LOGIN_REFRESH.format(pair.getKey(), pair.getValue());
@@ -172,7 +177,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
refresh.setRefreshCount(refreshCount);
// 设置登录缓存
RedisStrings.setJson(loginKey, UserCacheKeyDefine.LOGIN_TOKEN, refresh);
if (refreshCount < maxRefreshCount) {
if (refreshCount < appAuthenticationConfig.getMaxRefreshCount()) {
// 小于续签最大次数 则再次设置 refreshToken
RedisStrings.setJson(refreshKey, UserCacheKeyDefine.LOGIN_REFRESH, refresh);
} else {
@@ -214,7 +219,8 @@ public class AuthenticationServiceImpl implements AuthenticationService {
// 检查登录失败次数
String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(request.getUsername());
String failedCount = redisTemplate.opsForValue().get(failedCountKey);
if (failedCount != null && Integer.parseInt(failedCount) >= maxFailedLoginCount) {
if (failedCount != null
&& Integer.parseInt(failedCount) >= appAuthenticationConfig.getLoginFailedLockCount()) {
throw Exceptions.argument(ErrorMessage.MAX_LOGIN_FAILED);
}
}
@@ -235,23 +241,23 @@ public class AuthenticationServiceImpl implements AuthenticationService {
// 刷新登录失败缓存
String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(request.getUsername());
Long failedLoginCount = redisTemplate.opsForValue().increment(failedCountKey);
RedisUtils.setExpire(failedCountKey, UserCacheKeyDefine.LOGIN_FAILED_COUNT);
// 锁定用户
if (failedLoginCount >= maxFailedLoginCount) {
// 更新用户表
SystemUserDO updateUser = new SystemUserDO();
updateUser.setId(user.getId());
updateUser.setStatus(UserStatusEnum.LOCKED.getStatus());
systemUserDAO.updateById(updateUser);
// 修改缓存状态
String userInfoKey = UserCacheKeyDefine.USER_INFO.format(user.getId());
String userInfoCache = redisTemplate.opsForValue().get(userInfoKey);
if (userInfoCache != null) {
LoginUser loginUser = JSON.parseObject(userInfoCache, LoginUser.class);
loginUser.setStatus(UserStatusEnum.LOCKED.getStatus());
RedisStrings.setJson(userInfoKey, UserCacheKeyDefine.USER_INFO, loginUser);
}
}
RedisUtils.setExpire(failedCountKey, appAuthenticationConfig.getLoginFailedLockTime(), TimeUnit.MINUTES);
// // 锁定用户
// if (failedLoginCount >= appAuthenticationConfig.getLoginFailedLockCount()) {
// // 更新用户表
// SystemUserDO updateUser = new SystemUserDO();
// updateUser.setId(user.getId());
// updateUser.setStatus(UserStatusEnum.LOCKED.getStatus());
// systemUserDAO.updateById(updateUser);
// // 修改缓存状态
// String userInfoKey = UserCacheKeyDefine.USER_INFO.format(user.getId());
// String userInfoCache = redisTemplate.opsForValue().get(userInfoKey);
// if (userInfoCache != null) {
// LoginUser loginUser = JSON.parseObject(userInfoCache, LoginUser.class);
// loginUser.setStatus(UserStatusEnum.LOCKED.getStatus());
// RedisStrings.setJson(userInfoKey, UserCacheKeyDefine.USER_INFO, loginUser);
// }
// }
return false;
}
@@ -337,7 +343,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
}
}
// 删除续签信息
if (allowRefresh) {
if (appAuthenticationConfig.getAllowRefresh()) {
RedisUtils.scanKeysDelete(UserCacheKeyDefine.LOGIN_REFRESH.format(id, "*"));
}
}
@@ -365,7 +371,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
.build();
RedisStrings.setJson(loginKey, UserCacheKeyDefine.LOGIN_TOKEN, loginValue);
// 生成 refreshToken
if (allowRefresh) {
if (appAuthenticationConfig.getAllowRefresh()) {
String refreshKey = UserCacheKeyDefine.LOGIN_REFRESH.format(id, loginTime);
RedisStrings.setJson(refreshKey, UserCacheKeyDefine.LOGIN_REFRESH, loginValue);
}

View File

@@ -14,6 +14,7 @@ import com.orion.ops.framework.redis.core.utils.RedisStrings;
import com.orion.ops.framework.redis.core.utils.RedisUtils;
import com.orion.ops.framework.redis.core.utils.barrier.CacheBarriers;
import com.orion.ops.framework.security.core.utils.SecurityUtils;
import com.orion.ops.module.infra.config.AppAuthenticationConfig;
import com.orion.ops.module.infra.convert.SystemUserConvert;
import com.orion.ops.module.infra.dao.OperatorLogDAO;
import com.orion.ops.module.infra.dao.SystemRoleDAO;
@@ -49,6 +50,9 @@ import java.util.stream.Collectors;
@Service
public class SystemUserServiceImpl implements SystemUserService {
@Resource
private AppAuthenticationConfig appAuthenticationConfig;
@Resource
private SystemUserDAO systemUserDAO;
@@ -274,7 +278,7 @@ public class SystemUserServiceImpl implements SystemUserService {
// 删除登录缓存
RedisUtils.scanKeysDelete(UserCacheKeyDefine.LOGIN_TOKEN.format(id, "*"));
// 删除续签信息
if (AuthenticationService.allowRefresh) {
if (appAuthenticationConfig.getAllowRefresh()) {
RedisUtils.scanKeysDelete(UserCacheKeyDefine.LOGIN_REFRESH.format(id, "*"));
}
}