新增退出日志记录

This commit is contained in:
RuoYi 2018-03-08 15:03:55 +08:00
parent 720e079d20
commit 10761200dd
13 changed files with 194 additions and 34 deletions

View File

@ -23,6 +23,11 @@ public class CommonConstant
*/
public static final String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
public static final String Logout = "Logout";
/**
* 登录失败
*/

View File

@ -1,18 +0,0 @@
package com.ruoyi.common.utils;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 客户端工具类
*
* @author ruoyi
*/
public class HttpContextUtils
{
public static HttpServletRequest getHttpServletRequest()
{
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}

View File

@ -0,0 +1,54 @@
package com.ruoyi.common.utils;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 客户端工具类
*
* @author ruoyi
*/
public class ServletUtils
{
/**
* 获取request对象
*/
public static HttpServletRequest getHttpServletRequest()
{
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
/**
* 是否是Ajax异步请求
*/
public static boolean isAjaxRequest(HttpServletRequest request)
{
String accept = request.getHeader("accept");
if (accept != null && accept.indexOf("application/json") != -1)
{
return true;
}
String xRequestedWith = request.getHeader("X-Requested-With");
if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
{
return true;
}
String uri = request.getRequestURI();
if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
{
return true;
}
String ajax = request.getParameter("__ajax");
if (StringUtils.inStringIgnoreCase(ajax, "json", "xml"))
{
return true;
}
return false;
}
}

View File

@ -153,4 +153,25 @@ public class StringUtils
return (str == null ? "" : str.trim());
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs)
{
if (str != null && strs != null)
{
for (String s : strs)
{
if (str.equalsIgnoreCase(trim(s)))
{
return true;
}
}
}
return false;
}
}

View File

@ -41,7 +41,7 @@ public class SystemLogUtils
sys_user_logger.info(s.toString(), args);
if (CommonConstant.LOGIN_SUCCESS.equals(status))
if (CommonConstant.LOGIN_SUCCESS.equals(status) || CommonConstant.Logout.equals(status))
{
saveOpLog(username, msg, CommonConstant.SUCCESS);
}
@ -53,7 +53,7 @@ public class SystemLogUtils
public static void saveOpLog(String username, String message, String status)
{
UserAgent userAgent = UserAgent.parseUserAgentString(HttpContextUtils.getHttpServletRequest().getHeader("User-Agent"));
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getHttpServletRequest().getHeader("User-Agent"));
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();
// 获取客户端浏览器

View File

@ -33,6 +33,11 @@ public class ShiroUtils
return getUser().getUserId().longValue();
}
public static String getLoginName()
{
return getUser().getLoginName();
}
public static String getIp()
{
return getSubjct().getSession().getHost();

View File

@ -13,7 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.utils.HttpContextUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
@ -85,7 +85,7 @@ public class LogAspect
// 请求的地址
String ip = ShiroUtils.getIp();
operLog.setOperIp(ip);
operLog.setOperUrl(HttpContextUtils.getHttpServletRequest().getRequestURI());
operLog.setOperUrl(ServletUtils.getHttpServletRequest().getRequestURI());
if (currentUser != null)
{
operLog.setLoginName(currentUser.getLoginName());
@ -146,7 +146,7 @@ public class LogAspect
*/
private static void setRequestValue(OperLog operLog)
{
Map<String, String[]> map = HttpContextUtils.getHttpServletRequest().getParameterMap();
Map<String, String[]> map = ServletUtils.getHttpServletRequest().getParameterMap();
String params = JSONObject.toJSONString(map);
operLog.setOperParam(params);
}

View File

@ -7,7 +7,6 @@ import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
@ -15,10 +14,10 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.framework.shiro.realm.UserRealm;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
import com.ruoyi.framework.shiro.web.filter.LogoutFilter;
import com.ruoyi.framework.shiro.web.filter.online.OnlineSessionFilter;
import com.ruoyi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter;
import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager;
@ -173,6 +172,16 @@ public class ShiroConfig
return securityManager;
}
/**
* 退出过滤器
*/
public LogoutFilter logoutFilter()
{
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setLoginUrl(loginUrl);
return logoutFilter;
}
/**
* Shiro过滤器配置
*/
@ -186,9 +195,6 @@ public class ShiroConfig
shiroFilterFactoryBean.setLoginUrl(loginUrl);
// 权限认证失败则跳转到指定页面
shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
// 注销成功则跳转到指定页面
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setRedirectUrl(loginUrl);
// Shiro连接约束配置即过滤链的定义
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 对静态资源设置匿名访问
@ -212,6 +218,8 @@ public class ShiroConfig
Map<String, Filter> filters = new LinkedHashMap<>();
filters.put("onlineSession", onlineSessionFilter());
filters.put("syncOnlineSession", syncOnlineSessionFilter());
// 注销成功则跳转到指定页面
filters.put("logout", logoutFilter());
shiroFilterFactoryBean.setFilters(filters);
// 所有请求需要认证

View File

@ -6,7 +6,7 @@ import org.apache.shiro.session.mgt.SessionContext;
import org.apache.shiro.session.mgt.SessionFactory;
import org.apache.shiro.web.session.mgt.WebSessionContext;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.HttpContextUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.IpUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.monitor.online.domain.OnlineSession;
@ -43,7 +43,7 @@ public class OnlineSessionFactory implements SessionFactory
if (request != null)
{
UserAgent userAgent = UserAgent
.parseUserAgentString(HttpContextUtils.getHttpServletRequest().getHeader("User-Agent"));
.parseUserAgentString(ServletUtils.getHttpServletRequest().getHeader("User-Agent"));
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();
// 获取客户端浏览器

View File

@ -0,0 +1,81 @@
package com.ruoyi.framework.shiro.web.filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.subject.Subject;
import com.ruoyi.common.constant.CommonConstant;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SystemLogUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
/**
* 退出过滤器
*
* @author ruoyi
*/
@Slf4j
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
{
/**
* 退出后重定向的地址
*/
private String loginUrl;
public String getLoginUrl()
{
return 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
{
String loginName = ShiroUtils.getLoginName();
// 记录用户退出日志
SystemLogUtils.log(loginName, CommonConstant.Logout, MessageUtils.message("user.logout.success"));
// 退出登录
subject.logout();
}
catch (SessionException ise)
{
log.error("logout fail.", ise);
}
issueRedirect(request, response, redirectUrl);
}
catch (Exception e)
{
log.debug("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.isNoneBlank(url))
{
return url;
}
return super.getRedirectUrl(request, response, subject);
}
}

View File

@ -2,7 +2,7 @@ package com.ruoyi.framework.web.support;
import javax.servlet.http.HttpServletRequest;
import com.ruoyi.common.utils.HttpContextUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.MapDataUtil;
import com.ruoyi.framework.web.page.PageUtilEntity;
@ -18,7 +18,7 @@ public class TableSupport
*/
public static PageUtilEntity getPageUtilEntity()
{
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
HttpServletRequest request = ServletUtils.getHttpServletRequest();
PageUtilEntity pageUtilEntity = new PageUtilEntity();
pageUtilEntity.setPage(Integer.valueOf(request.getParameter("offset")));
pageUtilEntity.setSize(Integer.valueOf(request.getParameter("limit")));

View File

@ -6,6 +6,7 @@ user.password.retry.limit.count=密码输入错误{0}次,{1}
user.password.retry.limit.exceed=密码输入错误{0}次帐户锁定10分钟
user.blocked=用户已封禁,原因:{0}
role.blocked=角色已封禁,原因:{0}
user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间
@ -16,7 +17,6 @@ user.jcaptcha.error=验证码错误
user.email.not.valid=邮箱格式错误
user.mobile.phone.number.not.valid=手机号格式错误
user.logout.success=退出成功
user.login.success=登录成功
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录

View File

@ -26,7 +26,7 @@ $(function() {
},
{
field: 'status',
title: '登录状态',
title: '状态',
align: 'center',
formatter: function(value, row, index) {
if (value == 0) {
@ -36,6 +36,10 @@ $(function() {
}
}
},
{
field: 'msg',
title: '操作信息'
},
{
field: 'loginTime',
title: '登录时间'