mirror of https://gitee.com/y_project/RuoYi.git
1,增加异步管理和工厂两类。
2,修改常规操作为异步同步到数据库。 3,修改登陆日志为异步同步到数据库。 4,修改session为异步同步到数据库。 fix issue:登陆/操作等操作响应时间长。pull/23/MERGE
parent
fd75ee49d6
commit
f9c82e1f14
|
@ -2,11 +2,13 @@ package com.ruoyi.common.utils;
|
|||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
|
||||
import com.ruoyi.project.monitor.logininfor.service.LogininforServiceImpl;
|
||||
|
||||
import eu.bitwalker.useragentutils.UserAgent;
|
||||
|
||||
/**
|
||||
|
@ -14,58 +16,54 @@ import eu.bitwalker.useragentutils.UserAgent;
|
|||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SystemLogUtils
|
||||
{
|
||||
@Deprecated // 加入异步功能之后,该类已无意义
|
||||
public class SystemLogUtils {
|
||||
|
||||
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
|
||||
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
|
||||
|
||||
/**
|
||||
* 记录格式 [ip][用户名][操作][错误消息]
|
||||
* <p/>
|
||||
* 注意操作如下: loginError 登录失败 loginSuccess 登录成功 passwordError 密码错误 changePassword 修改密码 changeStatus 修改状态
|
||||
*
|
||||
* @param username
|
||||
* @param op
|
||||
* @param msg
|
||||
* @param args
|
||||
*/
|
||||
public static void log(String username, String status, String msg, Object... args)
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append(LogUtils.getBlock(ShiroUtils.getIp()));
|
||||
s.append(AddressUtils.getRealAddressByIP(ShiroUtils.getIp()));
|
||||
s.append(LogUtils.getBlock(username));
|
||||
s.append(LogUtils.getBlock(status));
|
||||
s.append(LogUtils.getBlock(msg));
|
||||
/**
|
||||
* 记录格式 [ip][用户名][操作][错误消息]
|
||||
* <p/>
|
||||
* 注意操作如下: loginError 登录失败 loginSuccess 登录成功 passwordError 密码错误
|
||||
* changePassword 修改密码 changeStatus 修改状态
|
||||
*
|
||||
* @param username
|
||||
* @param op
|
||||
* @param msg
|
||||
* @param args
|
||||
*/
|
||||
public static void log(String username, String status, String msg, Object... args) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append(LogUtils.getBlock(ShiroUtils.getIp()));
|
||||
s.append(AddressUtils.getRealAddressByIP(ShiroUtils.getIp()));
|
||||
s.append(LogUtils.getBlock(username));
|
||||
s.append(LogUtils.getBlock(status));
|
||||
s.append(LogUtils.getBlock(msg));
|
||||
|
||||
sys_user_logger.info(s.toString(), args);
|
||||
sys_user_logger.info(s.toString(), args);
|
||||
|
||||
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status))
|
||||
{
|
||||
saveOpLog(username, msg, Constants.SUCCESS);
|
||||
}
|
||||
else if (Constants.LOGIN_FAIL.equals(status))
|
||||
{
|
||||
saveOpLog(username, msg, Constants.FAIL);
|
||||
}
|
||||
}
|
||||
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status)) {
|
||||
saveOpLog(username, msg, Constants.SUCCESS);
|
||||
} else if (Constants.LOGIN_FAIL.equals(status)) {
|
||||
saveOpLog(username, msg, Constants.FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveOpLog(String username, String message, String status)
|
||||
{
|
||||
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||
// 获取客户端操作系统
|
||||
String os = userAgent.getOperatingSystem().getName();
|
||||
// 获取客户端浏览器
|
||||
String browser = userAgent.getBrowser().getName();
|
||||
LogininforServiceImpl logininforService = SpringUtils.getBean(LogininforServiceImpl.class);
|
||||
Logininfor logininfor = new Logininfor();
|
||||
logininfor.setLoginName(username);
|
||||
logininfor.setStatus(status);
|
||||
logininfor.setIpaddr(ShiroUtils.getIp());
|
||||
logininfor.setLoginLocation(AddressUtils.getRealAddressByIP(ShiroUtils.getIp()));
|
||||
logininfor.setBrowser(browser);
|
||||
logininfor.setOs(os);
|
||||
logininfor.setMsg(message);
|
||||
logininforService.insertLogininfor(logininfor);
|
||||
}
|
||||
public static void saveOpLog(String username, String message, String status) {
|
||||
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||
// 获取客户端操作系统
|
||||
String os = userAgent.getOperatingSystem().getName();
|
||||
// 获取客户端浏览器
|
||||
String browser = userAgent.getBrowser().getName();
|
||||
LogininforServiceImpl logininforService = SpringUtils.getBean(LogininforServiceImpl.class);
|
||||
Logininfor logininfor = new Logininfor();
|
||||
logininfor.setLoginName(username);
|
||||
logininfor.setStatus(status);
|
||||
logininfor.setIpaddr(ShiroUtils.getIp());
|
||||
logininfor.setLoginLocation(AddressUtils.getRealAddressByIP(ShiroUtils.getIp()));
|
||||
logininfor.setBrowser(browser);
|
||||
logininfor.setOs(os);
|
||||
logininfor.setMsg(message);
|
||||
logininforService.insertLogininfor(logininfor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.ruoyi.framework.aspectj;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import com.ruoyi.common.utils.AddressUtils;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.Signature;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
|
@ -12,18 +12,19 @@ import org.aspectj.lang.annotation.Pointcut;
|
|||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.framework.aspectj.lang.annotation.Log;
|
||||
import com.ruoyi.framework.aspectj.lang.constant.BusinessStatus;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.project.monitor.operlog.domain.OperLog;
|
||||
import com.ruoyi.project.monitor.operlog.service.IOperLogService;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
|
||||
/**
|
||||
|
@ -34,149 +35,128 @@ import com.ruoyi.project.system.user.domain.User;
|
|||
@Aspect
|
||||
@Component
|
||||
@EnableAsync
|
||||
public class LogAspect
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
|
||||
public class LogAspect {
|
||||
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
|
||||
|
||||
@Autowired
|
||||
private IOperLogService operLogService;
|
||||
// 配置织入点
|
||||
@Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.Log)")
|
||||
public void logPointCut() {
|
||||
}
|
||||
|
||||
// 配置织入点
|
||||
@Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.Log)")
|
||||
public void logPointCut()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* 前置通知 用于拦截操作
|
||||
*
|
||||
* @param joinPoint
|
||||
* 切点
|
||||
*/
|
||||
@AfterReturning(pointcut = "logPointCut()")
|
||||
public void doBefore(JoinPoint joinPoint) {
|
||||
handleLog(joinPoint, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 前置通知 用于拦截操作
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
*/
|
||||
@AfterReturning(pointcut = "logPointCut()")
|
||||
public void doBefore(JoinPoint joinPoint)
|
||||
{
|
||||
handleLog(joinPoint, null);
|
||||
}
|
||||
/**
|
||||
* 拦截异常操作
|
||||
*
|
||||
* @param joinPoint
|
||||
* @param e
|
||||
*/
|
||||
@AfterThrowing(value = "logPointCut()", throwing = "e")
|
||||
public void doAfter(JoinPoint joinPoint, Exception e) {
|
||||
handleLog(joinPoint, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截异常操作
|
||||
*
|
||||
* @param joinPoint
|
||||
* @param e
|
||||
*/
|
||||
@AfterThrowing(value = "logPointCut()", throwing = "e")
|
||||
public void doAfter(JoinPoint joinPoint, Exception e)
|
||||
{
|
||||
handleLog(joinPoint, e);
|
||||
}
|
||||
@Async
|
||||
protected void handleLog(final JoinPoint joinPoint, final Exception e) {
|
||||
try {
|
||||
// 获得注解
|
||||
Log controllerLog = getAnnotationLog(joinPoint);
|
||||
if (controllerLog == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Async
|
||||
protected void handleLog(final JoinPoint joinPoint, final Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获得注解
|
||||
Log controllerLog = getAnnotationLog(joinPoint);
|
||||
if (controllerLog == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// 获取当前的用户
|
||||
User currentUser = ShiroUtils.getUser();
|
||||
|
||||
// 获取当前的用户
|
||||
User currentUser = ShiroUtils.getUser();
|
||||
// *========数据库日志=========*//
|
||||
OperLog operLog = new OperLog();
|
||||
operLog.setStatus(BusinessStatus.SUCCESS);
|
||||
// 请求的地址
|
||||
String ip = ShiroUtils.getIp();
|
||||
operLog.setOperIp(ip);
|
||||
|
||||
// *========数据库日志=========*//
|
||||
OperLog operLog = new OperLog();
|
||||
operLog.setStatus(BusinessStatus.SUCCESS);
|
||||
// 请求的地址
|
||||
String ip = ShiroUtils.getIp();
|
||||
operLog.setOperIp(ip);
|
||||
// 操作地点
|
||||
operLog.setOperLocation(AddressUtils.getRealAddressByIP(ip));
|
||||
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
|
||||
if (currentUser != null) {
|
||||
operLog.setOperName(currentUser.getLoginName());
|
||||
if (StringUtils.isNotNull(currentUser.getDept()) && StringUtils.isNotEmpty(currentUser.getDept().getDeptName())) {
|
||||
operLog.setDeptName(currentUser.getDept().getDeptName());
|
||||
}
|
||||
}
|
||||
|
||||
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
|
||||
if (currentUser != null)
|
||||
{
|
||||
operLog.setOperName(currentUser.getLoginName());
|
||||
if (StringUtils.isNotNull(currentUser.getDept())
|
||||
&& StringUtils.isNotEmpty(currentUser.getDept().getDeptName()))
|
||||
{
|
||||
operLog.setDeptName(currentUser.getDept().getDeptName());
|
||||
}
|
||||
}
|
||||
if (e != null) {
|
||||
operLog.setStatus(BusinessStatus.FAIL);
|
||||
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
||||
}
|
||||
// 设置方法名称
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
operLog.setMethod(className + "." + methodName + "()");
|
||||
// 处理设置注解上的参数
|
||||
getControllerMethodDescription(controllerLog, operLog);
|
||||
// 保存数据库
|
||||
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
|
||||
} catch (Exception exp) {
|
||||
// 记录本地异常日志
|
||||
log.error("==前置通知异常==");
|
||||
log.error("异常信息:{}", exp.getMessage());
|
||||
exp.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (e != null)
|
||||
{
|
||||
operLog.setStatus(BusinessStatus.FAIL);
|
||||
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
||||
}
|
||||
// 设置方法名称
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
operLog.setMethod(className + "." + methodName + "()");
|
||||
// 处理设置注解上的参数
|
||||
getControllerMethodDescription(controllerLog, operLog);
|
||||
// 保存数据库
|
||||
operLogService.insertOperlog(operLog);
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
// 记录本地异常日志
|
||||
log.error("==前置通知异常==");
|
||||
log.error("异常信息:{}", exp.getMessage());
|
||||
exp.printStackTrace();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取注解中对方法的描述信息 用于Controller层注解
|
||||
*
|
||||
* @param joinPoint
|
||||
* 切点
|
||||
* @return 方法描述
|
||||
* @throws Exception
|
||||
*/
|
||||
public void getControllerMethodDescription(Log log, OperLog operLog) throws Exception {
|
||||
// 设置action动作
|
||||
operLog.setAction(log.action());
|
||||
// 设置标题
|
||||
operLog.setTitle(log.title());
|
||||
// 设置channel
|
||||
operLog.setChannel(log.channel());
|
||||
// 是否需要保存request,参数和值
|
||||
if (log.isSaveRequestData()) {
|
||||
// 获取参数的信息,传入到数据库中。
|
||||
setRequestValue(operLog);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取注解中对方法的描述信息 用于Controller层注解
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @return 方法描述
|
||||
* @throws Exception
|
||||
*/
|
||||
public void getControllerMethodDescription(Log log, OperLog operLog) throws Exception
|
||||
{
|
||||
// 设置action动作
|
||||
operLog.setAction(log.action());
|
||||
// 设置标题
|
||||
operLog.setTitle(log.title());
|
||||
// 设置channel
|
||||
operLog.setChannel(log.channel());
|
||||
// 是否需要保存request,参数和值
|
||||
if (log.isSaveRequestData())
|
||||
{
|
||||
// 获取参数的信息,传入到数据库中。
|
||||
setRequestValue(operLog);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取请求的参数,放到log中
|
||||
*
|
||||
* @param operLog
|
||||
* @param request
|
||||
*/
|
||||
private void setRequestValue(OperLog operLog) {
|
||||
Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
|
||||
String params = JSONObject.toJSONString(map);
|
||||
operLog.setOperParam(StringUtils.substring(params, 0, 255));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求的参数,放到log中
|
||||
*
|
||||
* @param operLog
|
||||
* @param request
|
||||
*/
|
||||
private void setRequestValue(OperLog operLog)
|
||||
{
|
||||
Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
|
||||
String params = JSONObject.toJSONString(map);
|
||||
operLog.setOperParam(StringUtils.substring(params, 0, 255));
|
||||
}
|
||||
/**
|
||||
* 是否存在注解,如果存在就获取
|
||||
*/
|
||||
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
|
||||
Signature signature = joinPoint.getSignature();
|
||||
MethodSignature methodSignature = (MethodSignature) signature;
|
||||
Method method = methodSignature.getMethod();
|
||||
|
||||
/**
|
||||
* 是否存在注解,如果存在就获取
|
||||
*/
|
||||
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
|
||||
{
|
||||
Signature signature = joinPoint.getSignature();
|
||||
MethodSignature methodSignature = (MethodSignature) signature;
|
||||
Method method = methodSignature.getMethod();
|
||||
|
||||
if (method != null)
|
||||
{
|
||||
return method.getAnnotation(Log.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (method != null) {
|
||||
return method.getAnnotation(Log.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package com.ruoyi.framework.manager;
|
||||
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 异步任务管理器
|
||||
*
|
||||
* @author liuhulu
|
||||
*/
|
||||
public class AsyncManager {
|
||||
// 操作延迟
|
||||
private final int OPERATE_DELAY_TIME = 10;
|
||||
// 异步操作此案城池
|
||||
private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);
|
||||
// 单例
|
||||
private static AsyncManager me = new AsyncManager();
|
||||
public static AsyncManager me() {
|
||||
return me;
|
||||
}
|
||||
// 执行任务
|
||||
public void execute(TimerTask task) {
|
||||
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package com.ruoyi.framework.manager.factory;
|
||||
|
||||
import java.util.TimerTask;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.utils.AddressUtils;
|
||||
import com.ruoyi.common.utils.LogUtils;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
|
||||
import com.ruoyi.project.monitor.logininfor.service.LogininforServiceImpl;
|
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession;
|
||||
import com.ruoyi.project.monitor.online.domain.UserOnline;
|
||||
import com.ruoyi.project.monitor.online.service.IUserOnlineService;
|
||||
import com.ruoyi.project.monitor.operlog.domain.OperLog;
|
||||
import com.ruoyi.project.monitor.operlog.service.IOperLogService;
|
||||
|
||||
import eu.bitwalker.useragentutils.UserAgent;
|
||||
|
||||
/**
|
||||
* 异步工厂(产生任务用)
|
||||
*
|
||||
* @author liuhulu
|
||||
*
|
||||
*/
|
||||
public class AsyncFactory {
|
||||
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
|
||||
|
||||
/**
|
||||
* 同步session到数据库
|
||||
*
|
||||
* @param operLog
|
||||
* @return
|
||||
*/
|
||||
public static TimerTask syncSessionToDb(final OnlineSession session) {
|
||||
return new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
UserOnline online = new UserOnline();
|
||||
online.setSessionId(String.valueOf(session.getId()));
|
||||
online.setDeptName(session.getDeptName());
|
||||
online.setLoginName(session.getLoginName());
|
||||
online.setStartTimestamp(session.getStartTimestamp());
|
||||
online.setLastAccessTime(session.getLastAccessTime());
|
||||
online.setExpireTime(session.getTimeout());
|
||||
online.setIpaddr(session.getHost());
|
||||
online.setLonginLocation(AddressUtils.getRealAddressByIP(session.getHost()));
|
||||
online.setBrowser(session.getBrowser());
|
||||
online.setOs(session.getOs());
|
||||
online.setStatus(session.getStatus());
|
||||
online.setSession(session);
|
||||
SpringUtils.getBean(IUserOnlineService.class).saveOnline(online);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 记录 操作log
|
||||
*
|
||||
* @param rc
|
||||
* @return
|
||||
*/
|
||||
public static TimerTask recordOper(final OperLog operLog) {
|
||||
return new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
// 远程查询操作地点
|
||||
operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
|
||||
SpringUtils.getBean(IOperLogService.class).insertOperlog(operLog);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登陆信息
|
||||
*
|
||||
* @param username
|
||||
* @param status
|
||||
* @param message
|
||||
* @param userAgent
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
public static TimerTask recordLogininfor(final String username, final String status, final String message, final Object... args) {
|
||||
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||
return new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append(LogUtils.getBlock(ShiroUtils.getIp()));
|
||||
s.append(AddressUtils.getRealAddressByIP(ShiroUtils.getIp()));
|
||||
s.append(LogUtils.getBlock(username));
|
||||
s.append(LogUtils.getBlock(status));
|
||||
s.append(LogUtils.getBlock(message));
|
||||
// 打印信息到日志
|
||||
sys_user_logger.info(s.toString(), args);
|
||||
// 获取客户端操作系统
|
||||
String os = userAgent.getOperatingSystem().getName();
|
||||
// 获取客户端浏览器
|
||||
String browser = userAgent.getBrowser().getName();
|
||||
// 封装对象
|
||||
Logininfor logininfor = new Logininfor();
|
||||
logininfor.setLoginName(username);
|
||||
logininfor.setIpaddr(ShiroUtils.getIp());
|
||||
logininfor.setLoginLocation(AddressUtils.getRealAddressByIP(ShiroUtils.getIp()));
|
||||
logininfor.setBrowser(browser);
|
||||
logininfor.setOs(os);
|
||||
logininfor.setMsg(message);
|
||||
// 日志状态
|
||||
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status)) {
|
||||
logininfor.setStatus(Constants.SUCCESS);
|
||||
} else if (Constants.LOGIN_FAIL.equals(status)) {
|
||||
logininfor.setStatus(Constants.FAIL);
|
||||
}
|
||||
// 插入数据
|
||||
SpringUtils.getBean(LogininforServiceImpl.class).insertLogininfor(logininfor);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@ package com.ruoyi.framework.shiro.service;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
|
@ -13,8 +14,9 @@ import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
|||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.SystemLogUtils;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
import com.ruoyi.project.system.user.domain.UserStatus;
|
||||
import com.ruoyi.project.system.user.service.IUserService;
|
||||
|
@ -25,104 +27,101 @@ import com.ruoyi.project.system.user.service.IUserService;
|
|||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class LoginService
|
||||
{
|
||||
@Autowired
|
||||
private PasswordService passwordService;
|
||||
public class LoginService {
|
||||
@Autowired
|
||||
private PasswordService passwordService;
|
||||
|
||||
@Autowired
|
||||
private IUserService userService;
|
||||
@Autowired
|
||||
private IUserService userService;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
public User login(String username, String password)
|
||||
{
|
||||
// 验证码校验
|
||||
if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
|
||||
throw new CaptchaException();
|
||||
}
|
||||
// 用户名或密码为空 错误
|
||||
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null"));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
// 密码如果不在指定范围内 错误
|
||||
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
public User login(String username, String password) {
|
||||
// 验证码校验
|
||||
if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA))) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
|
||||
// SystemLogUtils.log(username, Constants.LOGIN_FAIL,
|
||||
// MessageUtils.message("user.jcaptcha.error"));
|
||||
throw new CaptchaException();
|
||||
}
|
||||
// 用户名或密码为空 错误
|
||||
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
|
||||
// SystemLogUtils.log(username, Constants.LOGIN_FAIL,
|
||||
// MessageUtils.message("not.null"));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
// 密码如果不在指定范围内 错误
|
||||
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||
// SystemLogUtils.log(username, Constants.LOGIN_FAIL,
|
||||
// MessageUtils.message("user.password.not.match"));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
|
||||
// 用户名不在指定范围内 错误
|
||||
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
||||
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
// 用户名不在指定范围内 错误
|
||||
if (username.length() < UserConstants.USERNAME_MIN_LENGTH || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||
// SystemLogUtils.log(username, Constants.LOGIN_FAIL,
|
||||
// MessageUtils.message("user.password.not.match"));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
|
||||
// 查询用户信息
|
||||
User user = userService.selectUserByLoginName(username);
|
||||
// 查询用户信息
|
||||
User user = userService.selectUserByLoginName(username);
|
||||
|
||||
if (user == null && maybeMobilePhoneNumber(username))
|
||||
{
|
||||
user = userService.selectUserByPhoneNumber(username);
|
||||
}
|
||||
if (user == null && maybeMobilePhoneNumber(username)) {
|
||||
user = userService.selectUserByPhoneNumber(username);
|
||||
}
|
||||
|
||||
if (user == null && maybeEmail(username))
|
||||
{
|
||||
user = userService.selectUserByEmail(username);
|
||||
}
|
||||
if (user == null && maybeEmail(username)) {
|
||||
user = userService.selectUserByEmail(username);
|
||||
}
|
||||
|
||||
if (user == null || UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists"));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
if (user == null || UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
|
||||
// SystemLogUtils.log(username, Constants.LOGIN_FAIL,
|
||||
// MessageUtils.message("user.not.exists"));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
|
||||
passwordService.validate(user, password);
|
||||
passwordService.validate(user, password);
|
||||
|
||||
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark()));
|
||||
throw new UserBlockedException(user.getRemark());
|
||||
}
|
||||
SystemLogUtils.log(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
||||
recordLoginInfo(user);
|
||||
return user;
|
||||
}
|
||||
if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
|
||||
// SystemLogUtils.log(username, Constants.LOGIN_FAIL,
|
||||
// MessageUtils.message("user.blocked", user.getRemark()));
|
||||
throw new UserBlockedException(user.getRemark());
|
||||
}
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
|
||||
// SystemLogUtils.log(username, Constants.LOGIN_SUCCESS,
|
||||
// MessageUtils.message("user.login.success"));
|
||||
recordLoginInfo(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
private boolean maybeEmail(String username)
|
||||
{
|
||||
if (!username.matches(UserConstants.EMAIL_PATTERN))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private boolean maybeEmail(String username) {
|
||||
if (!username.matches(UserConstants.EMAIL_PATTERN)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean maybeMobilePhoneNumber(String username)
|
||||
{
|
||||
if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private boolean maybeMobilePhoneNumber(String username) {
|
||||
if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*/
|
||||
public void recordLoginInfo(User user)
|
||||
{
|
||||
user.setLoginIp(ShiroUtils.getIp());
|
||||
user.setLoginDate(DateUtils.getNowDate());
|
||||
userService.updateUserInfo(user);
|
||||
}
|
||||
/**
|
||||
* 记录登录信息
|
||||
*/
|
||||
public void recordLoginInfo(User user) {
|
||||
user.setLoginIp(ShiroUtils.getIp());
|
||||
user.setLoginDate(DateUtils.getNowDate());
|
||||
userService.updateUserInfo(user);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
package com.ruoyi.framework.shiro.service;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.shiro.cache.Cache;
|
||||
import org.apache.shiro.cache.CacheManager;
|
||||
import org.apache.shiro.crypto.hash.Md5Hash;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.SystemLogUtils;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
|
||||
/**
|
||||
|
@ -21,70 +25,66 @@ import com.ruoyi.project.system.user.domain.User;
|
|||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class PasswordService
|
||||
{
|
||||
public class PasswordService {
|
||||
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private Cache<String, AtomicInteger> loginRecordCache;
|
||||
private Cache<String, AtomicInteger> loginRecordCache;
|
||||
|
||||
@Value(value = "${user.password.maxRetryCount}")
|
||||
private String maxRetryCount;
|
||||
@Value(value = "${user.password.maxRetryCount}")
|
||||
private String maxRetryCount;
|
||||
|
||||
@PostConstruct
|
||||
public void init()
|
||||
{
|
||||
loginRecordCache = cacheManager.getCache("loginRecordCache");
|
||||
}
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
loginRecordCache = cacheManager.getCache("loginRecordCache");
|
||||
}
|
||||
|
||||
public void validate(User user, String password)
|
||||
{
|
||||
String loginName = user.getLoginName();
|
||||
public void validate(User user, String password) {
|
||||
String loginName = user.getLoginName();
|
||||
|
||||
AtomicInteger retryCount = loginRecordCache.get(loginName);
|
||||
AtomicInteger retryCount = loginRecordCache.get(loginName);
|
||||
|
||||
if (retryCount == null)
|
||||
{
|
||||
retryCount = new AtomicInteger(0);
|
||||
loginRecordCache.put(loginName, retryCount);
|
||||
}
|
||||
if (retryCount.incrementAndGet() > Integer.valueOf(maxRetryCount).intValue())
|
||||
{
|
||||
SystemLogUtils.log(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount));
|
||||
throw new UserPasswordRetryLimitExceedException(Integer.valueOf(maxRetryCount).intValue());
|
||||
}
|
||||
if (retryCount == null) {
|
||||
retryCount = new AtomicInteger(0);
|
||||
loginRecordCache.put(loginName, retryCount);
|
||||
}
|
||||
if (retryCount.incrementAndGet() > Integer.valueOf(maxRetryCount).intValue()) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed"), maxRetryCount));
|
||||
// SystemLogUtils.log(loginName, Constants.LOGIN_FAIL,
|
||||
// MessageUtils.message("user.password.retry.limit.exceed",
|
||||
// maxRetryCount));
|
||||
throw new UserPasswordRetryLimitExceedException(Integer.valueOf(maxRetryCount).intValue());
|
||||
}
|
||||
|
||||
if (!matches(user, password))
|
||||
{
|
||||
SystemLogUtils.log(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", retryCount, password));
|
||||
loginRecordCache.put(loginName, retryCount);
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
else
|
||||
{
|
||||
clearLoginRecordCache(loginName);
|
||||
}
|
||||
}
|
||||
if (!matches(user, password)) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count"), retryCount, password));
|
||||
// SystemLogUtils.log(loginName, Constants.LOGIN_FAIL,
|
||||
// MessageUtils.message("user.password.retry.limit.count",
|
||||
// retryCount, password));
|
||||
loginRecordCache.put(loginName, retryCount);
|
||||
throw new UserPasswordNotMatchException();
|
||||
} else {
|
||||
clearLoginRecordCache(loginName);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matches(User user, String newPassword)
|
||||
{
|
||||
return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
||||
}
|
||||
public boolean matches(User user, String newPassword) {
|
||||
return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
||||
}
|
||||
|
||||
public void clearLoginRecordCache(String username)
|
||||
{
|
||||
loginRecordCache.remove(username);
|
||||
}
|
||||
public void clearLoginRecordCache(String username) {
|
||||
loginRecordCache.remove(username);
|
||||
}
|
||||
|
||||
public String encryptPassword(String username, String password, String salt)
|
||||
{
|
||||
return new Md5Hash(username + password + salt).toHex().toString();
|
||||
}
|
||||
public String encryptPassword(String username, String password, String salt) {
|
||||
return new Md5Hash(username + password + salt).toHex().toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
//System.out.println(new PasswordService().encryptPassword("admin", "admin123", "111111"));
|
||||
//System.out.println(new PasswordService().encryptPassword("ry", "admin123", "222222"));
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
// System.out.println(new PasswordService().encryptPassword("admin",
|
||||
// "admin123", "111111"));
|
||||
// System.out.println(new PasswordService().encryptPassword("ry",
|
||||
// "admin123", "222222"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,14 @@ package com.ruoyi.framework.shiro.session;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession;
|
||||
import com.ruoyi.project.monitor.online.domain.UserOnline;
|
||||
import com.ruoyi.project.monitor.online.service.IUserOnlineService;
|
||||
|
@ -15,101 +19,90 @@ import com.ruoyi.project.monitor.online.service.IUserOnlineService;
|
|||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
|
||||
{
|
||||
/**
|
||||
* 同步session到数据库的周期 单位为毫秒(默认1分钟)
|
||||
*/
|
||||
@Value("${shiro.session.dbSyncPeriod}")
|
||||
private int dbSyncPeriod;
|
||||
public class OnlineSessionDAO extends EnterpriseCacheSessionDAO {
|
||||
/**
|
||||
* 同步session到数据库的周期 单位为毫秒(默认1分钟)
|
||||
*/
|
||||
@Value("${shiro.session.dbSyncPeriod}")
|
||||
private int dbSyncPeriod;
|
||||
|
||||
/**
|
||||
* 上次同步数据库的时间戳
|
||||
*/
|
||||
private static final String LAST_SYNC_DB_TIMESTAMP = OnlineSessionDAO.class.getName() + "LAST_SYNC_DB_TIMESTAMP";
|
||||
/**
|
||||
* 上次同步数据库的时间戳
|
||||
*/
|
||||
private static final String LAST_SYNC_DB_TIMESTAMP = OnlineSessionDAO.class.getName() + "LAST_SYNC_DB_TIMESTAMP";
|
||||
|
||||
@Autowired
|
||||
private IUserOnlineService onlineService;
|
||||
@Autowired
|
||||
private IUserOnlineService onlineService;
|
||||
|
||||
@Autowired
|
||||
private OnlineSessionFactory onlineSessionFactory;
|
||||
@Autowired
|
||||
private OnlineSessionFactory onlineSessionFactory;
|
||||
|
||||
public OnlineSessionDAO()
|
||||
{
|
||||
super();
|
||||
}
|
||||
public OnlineSessionDAO() {
|
||||
super();
|
||||
}
|
||||
|
||||
public OnlineSessionDAO(long expireTime)
|
||||
{
|
||||
super();
|
||||
}
|
||||
public OnlineSessionDAO(long expireTime) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据会话ID获取会话
|
||||
*
|
||||
* @param sessionId 会话ID
|
||||
* @return ShiroSession
|
||||
*/
|
||||
@Override
|
||||
protected Session doReadSession(Serializable sessionId)
|
||||
{
|
||||
UserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId));
|
||||
if (userOnline == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return onlineSessionFactory.createSession(userOnline);
|
||||
}
|
||||
/**
|
||||
* 根据会话ID获取会话
|
||||
*
|
||||
* @param sessionId
|
||||
* 会话ID
|
||||
* @return ShiroSession
|
||||
*/
|
||||
@Override
|
||||
protected Session doReadSession(Serializable sessionId) {
|
||||
UserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId));
|
||||
if (userOnline == null) {
|
||||
return null;
|
||||
}
|
||||
return onlineSessionFactory.createSession(userOnline);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
|
||||
*/
|
||||
public void syncToDb(OnlineSession onlineSession)
|
||||
{
|
||||
Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP);
|
||||
if (lastSyncTimestamp != null)
|
||||
{
|
||||
boolean needSync = true;
|
||||
long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime();
|
||||
if (deltaTime < dbSyncPeriod * 60 * 1000)
|
||||
{
|
||||
// 时间差不足 无需同步
|
||||
needSync = false;
|
||||
}
|
||||
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
|
||||
/**
|
||||
* 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
|
||||
*/
|
||||
public void syncToDb(OnlineSession onlineSession) {
|
||||
Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP);
|
||||
if (lastSyncTimestamp != null) {
|
||||
boolean needSync = true;
|
||||
long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime();
|
||||
if (deltaTime < dbSyncPeriod * 60 * 1000) {
|
||||
// 时间差不足 无需同步
|
||||
needSync = false;
|
||||
}
|
||||
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
|
||||
|
||||
// session 数据变更了 同步
|
||||
if (isGuest == false && onlineSession.isAttributeChanged())
|
||||
{
|
||||
needSync = true;
|
||||
}
|
||||
// session 数据变更了 同步
|
||||
if (isGuest == false && onlineSession.isAttributeChanged()) {
|
||||
needSync = true;
|
||||
}
|
||||
|
||||
if (needSync == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime());
|
||||
// 更新完后 重置标识
|
||||
if (onlineSession.isAttributeChanged())
|
||||
{
|
||||
onlineSession.resetAttributeChanged();
|
||||
}
|
||||
onlineService.saveOnline(UserOnline.fromOnlineSession(onlineSession));
|
||||
}
|
||||
if (needSync == false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime());
|
||||
// 更新完后 重置标识
|
||||
if (onlineSession.isAttributeChanged()) {
|
||||
onlineSession.resetAttributeChanged();
|
||||
}
|
||||
// onlineService.saveOnline(UserOnline.fromOnlineSession(onlineSession));
|
||||
AsyncManager.me().execute(AsyncFactory.syncSessionToDb(onlineSession));
|
||||
}
|
||||
|
||||
/**
|
||||
* 当会话过期/停止(如用户退出时)属性等会调用
|
||||
*/
|
||||
@Override
|
||||
protected void doDelete(Session session)
|
||||
{
|
||||
OnlineSession onlineSession = (OnlineSession) session;
|
||||
if (null == onlineSession)
|
||||
{
|
||||
return;
|
||||
}
|
||||
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
|
||||
onlineService.deleteOnlineById(String.valueOf(onlineSession.getId()));
|
||||
}
|
||||
/**
|
||||
* 当会话过期/停止(如用户退出时)属性等会调用
|
||||
*/
|
||||
@Override
|
||||
protected void doDelete(Session session) {
|
||||
OnlineSession onlineSession = (OnlineSession) session;
|
||||
if (null == onlineSession) {
|
||||
return;
|
||||
}
|
||||
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
|
||||
onlineService.deleteOnlineById(String.valueOf(onlineSession.getId()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,18 @@ package com.ruoyi.framework.shiro.web.filter;
|
|||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.apache.shiro.session.SessionException;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.SystemLogUtils;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
|
||||
/**
|
||||
|
@ -18,69 +21,58 @@ import com.ruoyi.project.system.user.domain.User;
|
|||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
|
||||
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter {
|
||||
private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
|
||||
|
||||
/**
|
||||
* 退出后重定向的地址
|
||||
*/
|
||||
private String loginUrl;
|
||||
/**
|
||||
* 退出后重定向的地址
|
||||
*/
|
||||
private String loginUrl;
|
||||
|
||||
public String getLoginUrl()
|
||||
{
|
||||
return loginUrl;
|
||||
}
|
||||
public String getLoginUrl() {
|
||||
return loginUrl;
|
||||
}
|
||||
|
||||
public void setLoginUrl(String loginUrl)
|
||||
{
|
||||
this.loginUrl = loginUrl;
|
||||
}
|
||||
public void setLoginUrl(String loginUrl) {
|
||||
this.loginUrl = loginUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
Subject subject = getSubject(request, response);
|
||||
String redirectUrl = getRedirectUrl(request, response, subject);
|
||||
try
|
||||
{
|
||||
User user = ShiroUtils.getUser();
|
||||
if (StringUtils.isNotNull(user))
|
||||
{
|
||||
String loginName = user.getLoginName();
|
||||
// 记录用户退出日志
|
||||
SystemLogUtils.log(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success"));
|
||||
}
|
||||
// 退出登录
|
||||
subject.logout();
|
||||
}
|
||||
catch (SessionException ise)
|
||||
{
|
||||
log.error("logout fail.", ise);
|
||||
}
|
||||
issueRedirect(request, response, redirectUrl);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("Encountered session exception during logout. This can generally safely be ignored.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
|
||||
try {
|
||||
Subject subject = getSubject(request, response);
|
||||
String redirectUrl = getRedirectUrl(request, response, subject);
|
||||
try {
|
||||
User user = ShiroUtils.getUser();
|
||||
if (StringUtils.isNotNull(user)) {
|
||||
String loginName = user.getLoginName();
|
||||
// 记录用户退出日志
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
|
||||
// SystemLogUtils.log(loginName, Constants.LOGOUT,
|
||||
// MessageUtils.message("user.logout.success"));
|
||||
}
|
||||
// 退出登录
|
||||
subject.logout();
|
||||
} catch (SessionException ise) {
|
||||
log.error("logout fail.", ise);
|
||||
}
|
||||
issueRedirect(request, response, redirectUrl);
|
||||
} catch (Exception e) {
|
||||
log.error("Encountered session exception during logout. This can generally safely be ignored.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出跳转URL
|
||||
*/
|
||||
@Override
|
||||
protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject)
|
||||
{
|
||||
String url = getLoginUrl();
|
||||
if (StringUtils.isNotEmpty(url))
|
||||
{
|
||||
return url;
|
||||
}
|
||||
return super.getRedirectUrl(request, response, subject);
|
||||
}
|
||||
/**
|
||||
* 退出跳转URL
|
||||
*/
|
||||
@Override
|
||||
protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject) {
|
||||
String url = getLoginUrl();
|
||||
if (StringUtils.isNotEmpty(url)) {
|
||||
return url;
|
||||
}
|
||||
return super.getRedirectUrl(request, response, subject);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,202 +1,174 @@
|
|||
package com.ruoyi.project.monitor.online.domain;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.ruoyi.common.utils.AddressUtils;
|
||||
import com.ruoyi.framework.web.domain.BaseEntity;
|
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession.OnlineStatus;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 当前在线会话 sys_user_online
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class UserOnline extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
/** 用户会话id */
|
||||
private String sessionId;
|
||||
public class UserOnline extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
/** 用户会话id */
|
||||
private String sessionId;
|
||||
|
||||
/** 部门名称 */
|
||||
private String deptName;
|
||||
/** 部门名称 */
|
||||
private String deptName;
|
||||
|
||||
/** 登录名称 */
|
||||
private String loginName;
|
||||
/** 登录名称 */
|
||||
private String loginName;
|
||||
|
||||
/** 登录IP地址 */
|
||||
private String ipaddr;
|
||||
/** 登录IP地址 */
|
||||
private String ipaddr;
|
||||
|
||||
/** 登录地址 */
|
||||
private String longinLocation;
|
||||
/** 登录地址 */
|
||||
private String longinLocation;
|
||||
|
||||
/** 浏览器类型 */
|
||||
private String browser;
|
||||
/** 浏览器类型 */
|
||||
private String browser;
|
||||
|
||||
/** 操作系统 */
|
||||
private String os;
|
||||
/** 操作系统 */
|
||||
private String os;
|
||||
|
||||
/** session创建时间 */
|
||||
private Date startTimestamp;
|
||||
/** session创建时间 */
|
||||
private Date startTimestamp;
|
||||
|
||||
/** session最后访问时间 */
|
||||
private Date lastAccessTime;
|
||||
/** session最后访问时间 */
|
||||
private Date lastAccessTime;
|
||||
|
||||
/** 超时时间,单位为分钟 */
|
||||
private Long expireTime;
|
||||
/** 超时时间,单位为分钟 */
|
||||
private Long expireTime;
|
||||
|
||||
/** 在线状态 */
|
||||
private OnlineStatus status = OnlineStatus.on_line;
|
||||
/** 在线状态 */
|
||||
private OnlineStatus status = OnlineStatus.on_line;
|
||||
|
||||
/** 备份的当前用户会话 */
|
||||
private OnlineSession session;
|
||||
/** 备份的当前用户会话 */
|
||||
private OnlineSession session;
|
||||
|
||||
/**
|
||||
* 设置session对象
|
||||
*/
|
||||
public static final UserOnline fromOnlineSession(OnlineSession session)
|
||||
{
|
||||
UserOnline online = new UserOnline();
|
||||
online.setSessionId(String.valueOf(session.getId()));
|
||||
online.setDeptName(session.getDeptName());
|
||||
online.setLoginName(session.getLoginName());
|
||||
online.setStartTimestamp(session.getStartTimestamp());
|
||||
online.setLastAccessTime(session.getLastAccessTime());
|
||||
online.setExpireTime(session.getTimeout());
|
||||
online.setIpaddr(session.getHost());
|
||||
online.setLonginLocation(AddressUtils.getRealAddressByIP(session.getHost()));
|
||||
online.setBrowser(session.getBrowser());
|
||||
online.setOs(session.getOs());
|
||||
online.setStatus(session.getStatus());
|
||||
online.setSession(session);
|
||||
return online;
|
||||
}
|
||||
/**
|
||||
* 设置session对象
|
||||
*/
|
||||
@Deprecated
|
||||
public static final UserOnline fromOnlineSession(OnlineSession session) {
|
||||
UserOnline online = new UserOnline();
|
||||
online.setSessionId(String.valueOf(session.getId()));
|
||||
online.setDeptName(session.getDeptName());
|
||||
online.setLoginName(session.getLoginName());
|
||||
online.setStartTimestamp(session.getStartTimestamp());
|
||||
online.setLastAccessTime(session.getLastAccessTime());
|
||||
online.setExpireTime(session.getTimeout());
|
||||
online.setIpaddr(session.getHost());
|
||||
online.setLonginLocation(AddressUtils.getRealAddressByIP(session.getHost()));
|
||||
online.setBrowser(session.getBrowser());
|
||||
online.setOs(session.getOs());
|
||||
online.setStatus(session.getStatus());
|
||||
online.setSession(session);
|
||||
return online;
|
||||
}
|
||||
|
||||
public String getSessionId()
|
||||
{
|
||||
return sessionId;
|
||||
}
|
||||
public String getSessionId() {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public void setSessionId(String sessionId)
|
||||
{
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
public void setSessionId(String sessionId) {
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
public String getDeptName()
|
||||
{
|
||||
return deptName;
|
||||
}
|
||||
public String getDeptName() {
|
||||
return deptName;
|
||||
}
|
||||
|
||||
public void setDeptName(String deptName)
|
||||
{
|
||||
this.deptName = deptName;
|
||||
}
|
||||
public void setDeptName(String deptName) {
|
||||
this.deptName = deptName;
|
||||
}
|
||||
|
||||
public String getLoginName()
|
||||
{
|
||||
return loginName;
|
||||
}
|
||||
public String getLoginName() {
|
||||
return loginName;
|
||||
}
|
||||
|
||||
public void setLoginName(String loginName)
|
||||
{
|
||||
this.loginName = loginName;
|
||||
}
|
||||
public void setLoginName(String loginName) {
|
||||
this.loginName = loginName;
|
||||
}
|
||||
|
||||
public String getIpaddr()
|
||||
{
|
||||
return ipaddr;
|
||||
}
|
||||
public String getIpaddr() {
|
||||
return ipaddr;
|
||||
}
|
||||
|
||||
public void setIpaddr(String ipaddr)
|
||||
{
|
||||
this.ipaddr = ipaddr;
|
||||
}
|
||||
public void setIpaddr(String ipaddr) {
|
||||
this.ipaddr = ipaddr;
|
||||
}
|
||||
|
||||
public String getLonginLocation()
|
||||
{
|
||||
return longinLocation;
|
||||
}
|
||||
public String getLonginLocation() {
|
||||
return longinLocation;
|
||||
}
|
||||
|
||||
public void setLonginLocation(String longinLocation)
|
||||
{
|
||||
this.longinLocation = longinLocation;
|
||||
}
|
||||
public void setLonginLocation(String longinLocation) {
|
||||
this.longinLocation = longinLocation;
|
||||
}
|
||||
|
||||
public String getBrowser()
|
||||
{
|
||||
return browser;
|
||||
}
|
||||
public String getBrowser() {
|
||||
return browser;
|
||||
}
|
||||
|
||||
public void setBrowser(String browser)
|
||||
{
|
||||
this.browser = browser;
|
||||
}
|
||||
public void setBrowser(String browser) {
|
||||
this.browser = browser;
|
||||
}
|
||||
|
||||
public String getOs()
|
||||
{
|
||||
return os;
|
||||
}
|
||||
public String getOs() {
|
||||
return os;
|
||||
}
|
||||
|
||||
public void setOs(String os)
|
||||
{
|
||||
this.os = os;
|
||||
}
|
||||
public void setOs(String os) {
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
public Date getStartTimestamp()
|
||||
{
|
||||
return startTimestamp;
|
||||
}
|
||||
public Date getStartTimestamp() {
|
||||
return startTimestamp;
|
||||
}
|
||||
|
||||
public void setStartTimestamp(Date startTimestamp)
|
||||
{
|
||||
this.startTimestamp = startTimestamp;
|
||||
}
|
||||
public void setStartTimestamp(Date startTimestamp) {
|
||||
this.startTimestamp = startTimestamp;
|
||||
}
|
||||
|
||||
public Date getLastAccessTime()
|
||||
{
|
||||
return lastAccessTime;
|
||||
}
|
||||
public Date getLastAccessTime() {
|
||||
return lastAccessTime;
|
||||
}
|
||||
|
||||
public void setLastAccessTime(Date lastAccessTime)
|
||||
{
|
||||
this.lastAccessTime = lastAccessTime;
|
||||
}
|
||||
public void setLastAccessTime(Date lastAccessTime) {
|
||||
this.lastAccessTime = lastAccessTime;
|
||||
}
|
||||
|
||||
public Long getExpireTime()
|
||||
{
|
||||
return expireTime;
|
||||
}
|
||||
public Long getExpireTime() {
|
||||
return expireTime;
|
||||
}
|
||||
|
||||
public void setExpireTime(Long expireTime)
|
||||
{
|
||||
this.expireTime = expireTime;
|
||||
}
|
||||
public void setExpireTime(Long expireTime) {
|
||||
this.expireTime = expireTime;
|
||||
}
|
||||
|
||||
public OnlineStatus getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
public OnlineStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(OnlineStatus status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
public void setStatus(OnlineStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public OnlineSession getSession()
|
||||
{
|
||||
return session;
|
||||
}
|
||||
public OnlineSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public void setSession(OnlineSession session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
public void setSession(OnlineSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "UserOnline [sessionId=" + sessionId + ", deptName=" + deptName + ", loginName=" + loginName
|
||||
+ ", ipaddr=" + ipaddr + ", browser=" + browser + ", os=" + os + ", startTimestamp=" + startTimestamp
|
||||
+ ", lastAccessTime=" + lastAccessTime + ", expireTime=" + expireTime + ", status=" + status
|
||||
+ ", session=" + session + "]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserOnline [sessionId=" + sessionId + ", deptName=" + deptName + ", loginName=" + loginName + ", ipaddr=" + ipaddr + ", browser=" + browser + ", os=" + os + ", startTimestamp=" + startTimestamp + ", lastAccessTime=" + lastAccessTime + ", expireTime=" + expireTime + ", status=" + status + ", session=" + session + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue