基于Shiro框架做日活统计
基本思想是,通过记录成功登陆的日志来做统计分析,通过使用shiro的过滤器链体系来记录账号和密码登陆或自动登陆的日志插入
- 第一步,写一个过滤器,继承自 UserFilter,重写 isAccessAllowed 方法,如下
···
package io.jcwl.modules.sys.shiro;
import io.jcwl.common.config.ShareRedis;
import io.jcwl.common.mq.RabbitmqSender;
import io.jcwl.modules.drives.entity.sys.LoginLogEntity;
import io.jcwl.modules.drives.service.sys.LoginLogService;
import io.jcwl.modules.sys.entity.SysUserEntity;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.UserFilter;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class LoginStateFilter extends UserFilter {
private static final Logger log = LoggerFactory.getLogger(LoginStateFilter.class);
RabbitmqSender rabbitmqSender;
ShareRedis shareRedis;
LoginLogService loginLogService;
public LoginStateFilter(RabbitmqSender rabbitmqSender, ShareRedis shareRedis, LoginLogService loginLogService) {
this.rabbitmqSender = rabbitmqSender;
this.shareRedis = shareRedis;
this.loginLogService = loginLogService;
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (isLoginRequest(request, response)) {
return true;
} else {
Subject subject = getSubject(request, response);
if (subject.getPrincipal() != null) {
Jedis jedis = shareRedis.getResource();
String key = "ls:" + subject.getSession().getId().toString();
if (jedis.setnx(key, "1") > 0) {
LoginLogEntity loginLogEntity = new LoginLogEntity();
Session session = subject.getSession();
loginLogEntity.setIp(session.getHost());
ShiroHttpServletRequest shiroHttpServletRequest = (ShiroHttpServletRequest)request;
loginLogEntity.setUserAgent(shiroHttpServletRequest.getHeader("User-Agent"));
loginLogEntity.setLoginTime(session.getStartTimestamp());
SysUserEntity sysUserEntity = (SysUserEntity) subject.getPrincipal();
loginLogEntity.setUserId(sysUserEntity.getUserId());
loginLogEntity.setUsername(sysUserEntity.getUsername());
loginLogService.save(loginLogEntity);
jedis.expire(key, 60 * 60);
jedis.close();
}
}
return subject.getPrincipal() != null;
}
}
}
···
如上,如果登陆成功的话,获取登陆成功的信息,再根据redis去判断当前会话日志有没有插入过,如果没有插入,则插入日志,接下来,则可以根据日志表来进行日活用户统计分析,及客户端分析之类,仅供参考。