1,增加异步管理和工厂两类。

2,修改常规操作为异步同步到数据库。
3,修改登陆日志为异步同步到数据库。
4,修改session为异步同步到数据库。

fix issue:登陆/操作等操作响应时间长。
pull/23/MERGE
liuhulu 2018-08-15 09:59:43 +08:00
parent fd75ee49d6
commit f9c82e1f14
9 changed files with 713 additions and 628 deletions

View File

@ -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,23 +16,23 @@ 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");
/**
* [ip][][][]
* <p/>
* loginError loginSuccess passwordError changePassword changeStatus
* 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)
{
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()));
@ -40,18 +42,14 @@ public class SystemLogUtils
sys_user_logger.info(s.toString(), args);
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status))
{
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status)) {
saveOpLog(username, msg, Constants.SUCCESS);
}
else if (Constants.LOGIN_FAIL.equals(status))
{
} else if (Constants.LOGIN_FAIL.equals(status)) {
saveOpLog(username, msg, Constants.FAIL);
}
}
public static void saveOpLog(String username, String message, String status)
{
public static void saveOpLog(String username, String message, String status) {
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();

View File

@ -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,27 +35,22 @@ import com.ruoyi.project.system.user.domain.User;
@Aspect
@Component
@EnableAsync
public class LogAspect
{
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()
{
public void logPointCut() {
}
/**
*
*
* @param joinPoint
* @param joinPoint
*
*/
@AfterReturning(pointcut = "logPointCut()")
public void doBefore(JoinPoint joinPoint)
{
public void doBefore(JoinPoint joinPoint) {
handleLog(joinPoint, null);
}
@ -65,20 +61,16 @@ public class LogAspect
* @param e
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfter(JoinPoint joinPoint, Exception e)
{
public void doAfter(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint, e);
}
@Async
protected void handleLog(final JoinPoint joinPoint, final Exception e)
{
try
{
protected void handleLog(final JoinPoint joinPoint, final Exception e) {
try {
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null)
{
if (controllerLog == null) {
return;
}
@ -91,22 +83,16 @@ public class LogAspect
// 请求的地址
String ip = ShiroUtils.getIp();
operLog.setOperIp(ip);
// 操作地点
operLog.setOperLocation(AddressUtils.getRealAddressByIP(ip));
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
if (currentUser != null)
{
if (currentUser != null) {
operLog.setOperName(currentUser.getLoginName());
if (StringUtils.isNotNull(currentUser.getDept())
&& StringUtils.isNotEmpty(currentUser.getDept().getDeptName()))
{
if (StringUtils.isNotNull(currentUser.getDept()) && StringUtils.isNotEmpty(currentUser.getDept().getDeptName())) {
operLog.setDeptName(currentUser.getDept().getDeptName());
}
}
if (e != null)
{
if (e != null) {
operLog.setStatus(BusinessStatus.FAIL);
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}
@ -117,10 +103,8 @@ public class LogAspect
// 处理设置注解上的参数
getControllerMethodDescription(controllerLog, operLog);
// 保存数据库
operLogService.insertOperlog(operLog);
}
catch (Exception exp)
{
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
} catch (Exception exp) {
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
@ -131,12 +115,12 @@ public class LogAspect
/**
* Controller
*
* @param joinPoint
* @param joinPoint
*
* @return
* @throws Exception
*/
public void getControllerMethodDescription(Log log, OperLog operLog) throws Exception
{
public void getControllerMethodDescription(Log log, OperLog operLog) throws Exception {
// 设置action动作
operLog.setAction(log.action());
// 设置标题
@ -144,8 +128,7 @@ public class LogAspect
// 设置channel
operLog.setChannel(log.channel());
// 是否需要保存request参数和值
if (log.isSaveRequestData())
{
if (log.isSaveRequestData()) {
// 获取参数的信息,传入到数据库中。
setRequestValue(operLog);
}
@ -157,8 +140,7 @@ public class LogAspect
* @param operLog
* @param request
*/
private void setRequestValue(OperLog operLog)
{
private void setRequestValue(OperLog operLog) {
Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
String params = JSONObject.toJSONString(map);
operLog.setOperParam(StringUtils.substring(params, 0, 255));
@ -167,14 +149,12 @@ public class LogAspect
/**
*
*/
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
{
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
if (method != null) {
return method.getAnnotation(Log.class);
}
return null;

View File

@ -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);
}
}

View File

@ -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);
}
};
}
}

View File

@ -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,8 +27,7 @@ import com.ruoyi.project.system.user.service.IUserService;
* @author ruoyi
*/
@Component
public class LoginService
{
public class LoginService {
@Autowired
private PasswordService passwordService;
@ -36,80 +37,79 @@ public class LoginService
/**
*
*/
public User login(String username, String password)
{
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"));
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))
{
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null"));
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)
{
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"));
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"));
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);
if (user == null && maybeMobilePhoneNumber(username))
{
if (user == null && maybeMobilePhoneNumber(username)) {
user = userService.selectUserByPhoneNumber(username);
}
if (user == null && maybeEmail(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"));
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);
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark()));
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());
}
SystemLogUtils.log(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
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))
{
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))
{
private boolean maybeMobilePhoneNumber(String username) {
if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN)) {
return false;
}
return true;
@ -118,8 +118,7 @@ public class LoginService
/**
*
*/
public void recordLoginInfo(User user)
{
public void recordLoginInfo(User user) {
user.setLoginIp(ShiroUtils.getIp());
user.setLoginDate(DateUtils.getNowDate());
userService.updateUserInfo(user);

View File

@ -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,8 +25,7 @@ import com.ruoyi.project.system.user.domain.User;
* @author ruoyi
*/
@Component
public class PasswordService
{
public class PasswordService {
@Autowired
private CacheManager cacheManager;
@ -33,58 +36,55 @@ public class PasswordService
private String maxRetryCount;
@PostConstruct
public void init()
{
public void init() {
loginRecordCache = cacheManager.getCache("loginRecordCache");
}
public void validate(User user, String password)
{
public void validate(User user, String password) {
String loginName = user.getLoginName();
AtomicInteger retryCount = loginRecordCache.get(loginName);
if (retryCount == null)
{
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));
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));
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
{
} else {
clearLoginRecordCache(loginName);
}
}
public boolean matches(User user, String newPassword)
{
public boolean matches(User user, String newPassword) {
return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
}
public void clearLoginRecordCache(String username)
{
public void clearLoginRecordCache(String username) {
loginRecordCache.remove(username);
}
public String encryptPassword(String username, String password, String salt)
{
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"));
}
}

View File

@ -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,8 +19,7 @@ import com.ruoyi.project.monitor.online.service.IUserOnlineService;
*
* @author ruoyi
*/
public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
{
public class OnlineSessionDAO extends EnterpriseCacheSessionDAO {
/**
* session 1
*/
@ -34,28 +37,25 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
@Autowired
private OnlineSessionFactory onlineSessionFactory;
public OnlineSessionDAO()
{
public OnlineSessionDAO() {
super();
}
public OnlineSessionDAO(long expireTime)
{
public OnlineSessionDAO(long expireTime) {
super();
}
/**
* ID
*
* @param sessionId ID
* @param sessionId
* ID
* @return ShiroSession
*/
@Override
protected Session doReadSession(Serializable sessionId)
{
protected Session doReadSession(Serializable sessionId) {
UserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId));
if (userOnline == null)
{
if (userOnline == null) {
return null;
}
return onlineSessionFactory.createSession(userOnline);
@ -64,49 +64,42 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
/**
* 访///
*/
public void syncToDb(OnlineSession onlineSession)
{
public void syncToDb(OnlineSession onlineSession) {
Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP);
if (lastSyncTimestamp != null)
{
if (lastSyncTimestamp != null) {
boolean needSync = true;
long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime();
if (deltaTime < dbSyncPeriod * 60 * 1000)
{
if (deltaTime < dbSyncPeriod * 60 * 1000) {
// 时间差不足 无需同步
needSync = false;
}
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
// session 数据变更了 同步
if (isGuest == false && onlineSession.isAttributeChanged())
{
if (isGuest == false && onlineSession.isAttributeChanged()) {
needSync = true;
}
if (needSync == false)
{
if (needSync == false) {
return;
}
}
onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime());
// 更新完后 重置标识
if (onlineSession.isAttributeChanged())
{
if (onlineSession.isAttributeChanged()) {
onlineSession.resetAttributeChanged();
}
onlineService.saveOnline(UserOnline.fromOnlineSession(onlineSession));
// onlineService.saveOnline(UserOnline.fromOnlineSession(onlineSession));
AsyncManager.me().execute(AsyncFactory.syncSessionToDb(onlineSession));
}
/**
* /退
*/
@Override
protected void doDelete(Session session)
{
protected void doDelete(Session session) {
OnlineSession onlineSession = (OnlineSession) session;
if (null == onlineSession)
{
if (null == onlineSession) {
return;
}
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);

View File

@ -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,8 +21,7 @@ import com.ruoyi.project.system.user.domain.User;
*
* @author ruoyi
*/
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
{
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter {
private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
/**
@ -27,43 +29,35 @@ public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
*/
private String loginUrl;
public String getLoginUrl()
{
public String getLoginUrl() {
return loginUrl;
}
public void setLoginUrl(String loginUrl)
{
public void setLoginUrl(String loginUrl) {
this.loginUrl = loginUrl;
}
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
{
try
{
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
try {
Subject subject = getSubject(request, response);
String redirectUrl = getRedirectUrl(request, response, subject);
try
{
try {
User user = ShiroUtils.getUser();
if (StringUtils.isNotNull(user))
{
if (StringUtils.isNotNull(user)) {
String loginName = user.getLoginName();
// 记录用户退出日志
SystemLogUtils.log(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success"));
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)
{
} catch (SessionException ise) {
log.error("logout fail.", ise);
}
issueRedirect(request, response, redirectUrl);
}
catch (Exception e)
{
} catch (Exception e) {
log.error("Encountered session exception during logout. This can generally safely be ignored.", e);
}
return false;
@ -73,11 +67,9 @@ public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
* 退URL
*/
@Override
protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject)
{
protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject) {
String url = getLoginUrl();
if (StringUtils.isNotEmpty(url))
{
if (StringUtils.isNotEmpty(url)) {
return url;
}
return super.getRedirectUrl(request, response, subject);

View File

@ -1,17 +1,17 @@
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
{
public class UserOnline extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 用户会话id */
private String sessionId;
@ -52,8 +52,8 @@ public class UserOnline extends BaseEntity
/**
* session
*/
public static final UserOnline fromOnlineSession(OnlineSession session)
{
@Deprecated
public static final UserOnline fromOnlineSession(OnlineSession session) {
UserOnline online = new UserOnline();
online.setSessionId(String.valueOf(session.getId()));
online.setDeptName(session.getDeptName());
@ -70,133 +70,105 @@ public class UserOnline extends BaseEntity
return online;
}
public String getSessionId()
{
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId)
{
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public String getDeptName()
{
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName)
{
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getLoginName()
{
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName)
{
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getIpaddr()
{
public String getIpaddr() {
return ipaddr;
}
public void setIpaddr(String ipaddr)
{
public void setIpaddr(String ipaddr) {
this.ipaddr = ipaddr;
}
public String getLonginLocation()
{
public String getLonginLocation() {
return longinLocation;
}
public void setLonginLocation(String longinLocation)
{
public void setLonginLocation(String longinLocation) {
this.longinLocation = longinLocation;
}
public String getBrowser()
{
public String getBrowser() {
return browser;
}
public void setBrowser(String browser)
{
public void setBrowser(String browser) {
this.browser = browser;
}
public String getOs()
{
public String getOs() {
return os;
}
public void setOs(String os)
{
public void setOs(String os) {
this.os = os;
}
public Date getStartTimestamp()
{
public Date getStartTimestamp() {
return startTimestamp;
}
public void setStartTimestamp(Date startTimestamp)
{
public void setStartTimestamp(Date startTimestamp) {
this.startTimestamp = startTimestamp;
}
public Date getLastAccessTime()
{
public Date getLastAccessTime() {
return lastAccessTime;
}
public void setLastAccessTime(Date lastAccessTime)
{
public void setLastAccessTime(Date lastAccessTime) {
this.lastAccessTime = lastAccessTime;
}
public Long getExpireTime()
{
public Long getExpireTime() {
return expireTime;
}
public void setExpireTime(Long expireTime)
{
public void setExpireTime(Long expireTime) {
this.expireTime = expireTime;
}
public OnlineStatus getStatus()
{
public OnlineStatus getStatus() {
return status;
}
public void setStatus(OnlineStatus status)
{
public void setStatus(OnlineStatus status) {
this.status = status;
}
public OnlineSession getSession()
{
public OnlineSession getSession() {
return session;
}
public void setSession(OnlineSession 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 + "]";
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 + "]";
}
}