重构登录日志

This commit is contained in:
数据小王子 2024-02-27 17:31:16 +08:00
parent 3f829e271d
commit 5a814b947c
8 changed files with 78 additions and 73 deletions

View File

@ -1,26 +1,30 @@
package com.ruoyi.common.security.listener; package com.ruoyi.web.listener;
import cn.dev33.satoken.config.SaTokenConfig; import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.listener.SaTokenListener; import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.SaLoginModel;
import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil; import cn.hutool.http.useragent.UserAgentUtil;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.core.domain.dto.UserOnlineDTO;
import com.ruoyi.common.core.core.domain.model.LoginUser;
import com.ruoyi.common.core.enums.UserType;
import com.ruoyi.common.redis.utils.RedisUtils;
import com.ruoyi.common.security.utils.LoginHelper;
import com.ruoyi.common.core.utils.ip.AddressUtils;
import com.ruoyi.common.core.utils.ServletUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.core.domain.dto.UserOnlineDTO;
import com.ruoyi.common.core.utils.MessageUtils;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.common.core.utils.ip.AddressUtils;
import com.ruoyi.common.log.event.LogininforEvent;
import com.ruoyi.common.redis.utils.RedisUtils;
import com.ruoyi.common.security.utils.LoginHelper;
import com.ruoyi.common.tenant.helper.TenantHelper;
import com.ruoyi.web.service.SysLoginService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.Duration; import java.time.Duration;
/** /**
* 用户行为 自定义侦听器 * 用户行为 侦听器的实现
* *
* @author Lion Li * @author Lion Li
*/ */
@ -30,17 +34,15 @@ import java.time.Duration;
public class UserActionListener implements SaTokenListener { public class UserActionListener implements SaTokenListener {
private final SaTokenConfig tokenConfig; private final SaTokenConfig tokenConfig;
private final SysLoginService loginService;
/** /**
* 每次登录时触发 * 每次登录时触发
*/ */
@Override @Override
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) { public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
UserType userType = UserType.getUserType(loginId.toString());
if (userType == UserType.SYS_USER) {
UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
String ip = ServletUtils.getClientIP(); String ip = ServletUtils.getClientIP();
LoginUser user = LoginHelper.getLoginUser();
UserOnlineDTO dto = new UserOnlineDTO(); UserOnlineDTO dto = new UserOnlineDTO();
dto.setIpaddr(ip); dto.setIpaddr(ip);
dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
@ -48,17 +50,30 @@ public class UserActionListener implements SaTokenListener {
dto.setOs(userAgent.getOs().getName()); dto.setOs(userAgent.getOs().getName());
dto.setLoginTime(System.currentTimeMillis()); dto.setLoginTime(System.currentTimeMillis());
dto.setTokenId(tokenValue); dto.setTokenId(tokenValue);
dto.setUserName(user.getUsername()); String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY);
dto.setDeptName(user.getDeptName()); Long tenantId = (Long) loginModel.getExtra(LoginHelper.TENANT_KEY);
dto.setUserName(username);
dto.setClientKey((String) loginModel.getExtra(LoginHelper.CLIENT_KEY));
dto.setDeviceType(loginModel.getDevice());
dto.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY));
TenantHelper.dynamic(tenantId, () -> {
if(tokenConfig.getTimeout() == -1) { if(tokenConfig.getTimeout() == -1) {
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto); RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto);
} else { } else {
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout())); RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout()));
} }
});
// 记录登录日志
LogininforEvent logininforEvent = new LogininforEvent();
logininforEvent.setTenantId(tenantId);
logininforEvent.setUsername(username);
logininforEvent.setStatus(Constants.LOGIN_SUCCESS);
logininforEvent.setMessage(MessageUtils.message("user.login.success"));
logininforEvent.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(logininforEvent);
// 更新登录信息
loginService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip);
log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue); log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue);
} else if (userType == UserType.APP_USER) {
// app端 自行根据业务编写
}
} }
/** /**

View File

@ -244,11 +244,17 @@ public class SysLoginService {
* @param userId 用户ID * @param userId 用户ID
*/ */
public void recordLoginInfo(Long userId, String ip) { public void recordLoginInfo(Long userId, String ip) {
SysUserVo sysUserVo = userService.selectUserById(userId);
if (ObjectUtil.isNull(sysUserVo)) {
return;
}
SysUser sysUser = new SysUser(); SysUser sysUser = new SysUser();
sysUser.setUserId(userId); sysUser.setUserId(userId);
sysUser.setLoginIp(ip); sysUser.setLoginIp(ip);
sysUser.setLoginDate(DateUtils.getNowDate()); sysUser.setLoginDate(DateUtils.getNowDate());
sysUser.setUpdateBy(userId); sysUser.setUpdateBy(userId);
sysUser.setVersion(sysUserVo.getVersion());
userService.updateById(sysUser); userService.updateById(sysUser);
} }

View File

@ -5,7 +5,6 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.core.domain.model.EmailLoginBody; import com.ruoyi.common.core.core.domain.model.EmailLoginBody;
import com.ruoyi.common.json.utils.JsonUtils; import com.ruoyi.common.json.utils.JsonUtils;
import com.ruoyi.common.tenant.helper.TenantHelper;
import com.ruoyi.system.domain.vo.SysClientVo; import com.ruoyi.system.domain.vo.SysClientVo;
import com.ruoyi.system.domain.vo.SysUserVo; import com.ruoyi.system.domain.vo.SysUserVo;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
@ -70,9 +69,6 @@ public class EmailAuthStrategy implements IAuthStrategy {
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);
// loginService.recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
// loginService.recordLoginInfo(user.getUserId());
LoginVo loginVo = new LoginVo(); LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue()); loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout()); loginVo.setExpireIn(StpUtil.getTokenTimeout());

View File

@ -6,7 +6,6 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.core.domain.model.PasswordLoginBody; import com.ruoyi.common.core.core.domain.model.PasswordLoginBody;
import com.ruoyi.common.json.utils.JsonUtils; import com.ruoyi.common.json.utils.JsonUtils;
import com.ruoyi.common.tenant.helper.TenantHelper;
import com.ruoyi.system.domain.vo.SysClientVo; import com.ruoyi.system.domain.vo.SysClientVo;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -26,7 +25,6 @@ import com.ruoyi.common.core.utils.ValidatorUtils;
import com.ruoyi.common.redis.utils.RedisUtils; import com.ruoyi.common.redis.utils.RedisUtils;
import com.ruoyi.common.security.utils.LoginHelper; import com.ruoyi.common.security.utils.LoginHelper;
import com.ruoyi.common.web.config.properties.CaptchaProperties; import com.ruoyi.common.web.config.properties.CaptchaProperties;
import com.ruoyi.system.domain.SysClient;
import com.ruoyi.system.domain.vo.SysUserVo; import com.ruoyi.system.domain.vo.SysUserVo;
import com.ruoyi.web.domain.vo.LoginVo; import com.ruoyi.web.domain.vo.LoginVo;
import com.ruoyi.web.service.IAuthStrategy; import com.ruoyi.web.service.IAuthStrategy;
@ -81,9 +79,6 @@ public class PasswordAuthStrategy implements IAuthStrategy {
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);
// loginService.recordLogininfor(loginUser.getTenantId(), username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
// loginService.recordLoginInfo(user.getUserId(),user.getVersion());
LoginVo loginVo = new LoginVo(); LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue()); loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout()); loginVo.setExpireIn(StpUtil.getTokenTimeout());

View File

@ -3,10 +3,7 @@ package com.ruoyi.web.service.impl;
import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -23,11 +20,9 @@ import com.ruoyi.common.json.utils.JsonUtils;
import com.ruoyi.common.security.utils.LoginHelper; import com.ruoyi.common.security.utils.LoginHelper;
import com.ruoyi.common.social.config.properties.SocialProperties; import com.ruoyi.common.social.config.properties.SocialProperties;
import com.ruoyi.common.social.utils.SocialUtils; import com.ruoyi.common.social.utils.SocialUtils;
import com.ruoyi.common.tenant.helper.TenantHelper;
import com.ruoyi.system.domain.vo.SysClientVo; import com.ruoyi.system.domain.vo.SysClientVo;
import com.ruoyi.system.domain.vo.SysSocialVo; import com.ruoyi.system.domain.vo.SysSocialVo;
import com.ruoyi.system.domain.vo.SysUserVo; import com.ruoyi.system.domain.vo.SysUserVo;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysSocialService; import com.ruoyi.system.service.ISysSocialService;
import com.ruoyi.web.domain.vo.LoginVo; import com.ruoyi.web.domain.vo.LoginVo;
import com.ruoyi.web.service.IAuthStrategy; import com.ruoyi.web.service.IAuthStrategy;

View File

@ -12,7 +12,6 @@ import com.ruoyi.common.core.enums.UserStatus;
import com.ruoyi.common.core.utils.ValidatorUtils; import com.ruoyi.common.core.utils.ValidatorUtils;
import com.ruoyi.common.json.utils.JsonUtils; import com.ruoyi.common.json.utils.JsonUtils;
import com.ruoyi.common.security.utils.LoginHelper; import com.ruoyi.common.security.utils.LoginHelper;
import com.ruoyi.system.domain.SysClient;
import com.ruoyi.system.domain.vo.SysClientVo; import com.ruoyi.system.domain.vo.SysClientVo;
import com.ruoyi.system.domain.vo.SysUserVo; import com.ruoyi.system.domain.vo.SysUserVo;
import com.ruoyi.web.domain.vo.LoginVo; import com.ruoyi.web.domain.vo.LoginVo;

View File

@ -34,6 +34,16 @@ public class UserOnlineDTO implements Serializable {
*/ */
private String userName; private String userName;
/**
* 客户端
*/
private String clientKey;
/**
* 设备类型
*/
private String deviceType;
/** /**
* 登录IP地址 * 登录IP地址
*/ */

View File

@ -15,7 +15,6 @@ import com.ruoyi.common.core.core.domain.model.LoginUser;
import com.ruoyi.common.core.enums.UserType; import com.ruoyi.common.core.enums.UserType;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
/** /**
* 登录鉴权助手 * 登录鉴权助手
@ -35,9 +34,10 @@ public class LoginHelper {
public static final String LOGIN_USER_KEY = "loginUser"; public static final String LOGIN_USER_KEY = "loginUser";
public static final String TENANT_KEY = "tenantId"; public static final String TENANT_KEY = "tenantId";
public static final String USER_KEY = "userId"; public static final String USER_KEY = "userId";
public static final String USER_NAME_KEY = "userName";
public static final String DEPT_KEY = "deptId"; public static final String DEPT_KEY = "deptId";
public static final String DEPT_NAME_KEY = "deptName";
public static final String CLIENT_KEY = "clientid"; public static final String CLIENT_KEY = "clientid";
public static final String TENANT_ADMIN_KEY = "isTenantAdmin";
/** /**
* 登录系统 基于 设备类型 * 登录系统 基于 设备类型
@ -57,7 +57,11 @@ public class LoginHelper {
StpUtil.login(loginUser.getLoginId(), StpUtil.login(loginUser.getLoginId(),
model.setExtra(TENANT_KEY, loginUser.getTenantId()) model.setExtra(TENANT_KEY, loginUser.getTenantId())
.setExtra(USER_KEY, loginUser.getUserId()) .setExtra(USER_KEY, loginUser.getUserId())
.setExtra(DEPT_KEY, loginUser.getDeptId())); .setExtra(DEPT_KEY, loginUser.getDeptId())
.setExtra(TENANT_KEY, loginUser.getTenantId())
.setExtra(DEPT_NAME_KEY, loginUser.getDeptName())
.setExtra(USER_NAME_KEY, loginUser.getUsername())
);
SaSession tokenSession = StpUtil.getTokenSession(); SaSession tokenSession = StpUtil.getTokenSession();
tokenSession.updateTimeout(model.getTimeout()); tokenSession.updateTimeout(model.getTimeout());
tokenSession.set(LOGIN_USER_KEY, loginUser); tokenSession.set(LOGIN_USER_KEY, loginUser);
@ -67,13 +71,11 @@ public class LoginHelper {
* 获取用户(多级缓存) * 获取用户(多级缓存)
*/ */
public static LoginUser getLoginUser() { public static LoginUser getLoginUser() {
return (LoginUser) getStorageIfAbsentSet(LOGIN_USER_KEY, () -> {
SaSession session = StpUtil.getTokenSession(); SaSession session = StpUtil.getTokenSession();
if (ObjectUtil.isNull(session)) { if (ObjectUtil.isNull(session)) {
return null; return null;
} }
return session.get(LOGIN_USER_KEY); return (LoginUser) session.get(LOGIN_USER_KEY);
});
} }
/** /**
@ -109,7 +111,11 @@ public class LoginHelper {
} }
private static Object getExtra(String key) { private static Object getExtra(String key) {
return getStorageIfAbsentSet(key, () -> StpUtil.getExtra(key)); try {
return StpUtil.getExtra(key);
} catch (Exception e) {
return null;
}
} }
/** /**
@ -152,27 +158,10 @@ public class LoginHelper {
} }
public static boolean isTenantAdmin() { public static boolean isTenantAdmin() {
Object value = getStorageIfAbsentSet(TENANT_ADMIN_KEY, () -> { return Convert.toBool(isTenantAdmin(getLoginUser().getRolePermission()));
return isTenantAdmin(getLoginUser().getRolePermission());
});
return Convert.toBool(value);
} }
public static boolean isLogin() { public static boolean isLogin() {
return getLoginUser() != null; return getLoginUser() != null;
} }
public static Object getStorageIfAbsentSet(String key, Supplier<Object> handle) {
try {
Object obj = SaHolder.getStorage().get(key);
if (ObjectUtil.isNull(obj)) {
obj = handle.get();
SaHolder.getStorage().set(key, obj);
}
return obj;
} catch (Exception e) {
return null;
}
}
} }