Shiro获取在线用户
Shiro获取在线用户功能
1、定义ShiroSessionListener类🐭
/**
* @version 1.0.0
* @className: ShiroSessionListener
* @description:
* @author: LiJunYi
* @create: 2022/5/10 14:50
*/
public class ShiroSessionListener implements SessionListener
{
private final AtomicInteger sessionCount = new AtomicInteger(0);
@Override
public void onStart(Session session) {
sessionCount.incrementAndGet();
}
@Override
public void onStop(Session session) {
sessionCount.decrementAndGet();
}
@Override
public void onExpiration(Session session) {
sessionCount.decrementAndGet();
}
}
2、ShiroConfig的配置
2.1、Ehcache版本
@Configuration
public class ShiroConfig {
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
securityManager.setRememberMeManager(rememberMeManager());
securityManager.setCacheManager(ehCacheManager());
securityManager.setSessionManager(sessionManager());
return securityManager;
}
@Bean
public SessionDAO sessionDAO()
{
// 注意这块
MemorySessionDAO sessionDAO = new MemorySessionDAO();
return sessionDAO;
}
@Bean
public SessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
Collection<SessionListener> listeners = new ArrayList<SessionListener>();
listeners.add(new ShiroSessionListener());
sessionManager.setSessionListeners(listeners);
sessionManager.setSessionDAO(sessionDAO());
return sessionManager;
}
}
2.2、Redis版本
@Configuration
public class ShiroConfig
{
@Bean
public RedisManager redisManager()
{
RedisManager redisManager = new RedisManager();
redisManager.setHost(redisHost + ":" + redisPort);
redisManager.setDatabase(database);
if (StrUtil.isNotEmpty(password))
{
redisManager.setPassword(password);
}
redisManager.setTimeout(30 * 60);
return redisManager;
}
@Bean
public RedisCacheManager redisCacheManager()
{
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
redisCacheManager.setPrincipalIdFieldName("userId");
return redisCacheManager;
}
@Bean
public RedisSessionDAO sessionDAO()
{
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
return redisSessionDAO;
}
@Bean
public SessionManager sessionManager()
{
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
Collection<SessionListener> listeners = new ArrayList<SessionListener>();
listeners.add(new ShiroSessionListener());
sessionManager.setSessionListeners(listeners);
sessionManager.setSessionDAO(sessionDAO());
return sessionManager;
}
@Bean
public SecurityManager securityManager()
{
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
securityManager.setRememberMeManager(rememberMeManager());
securityManager.setCacheManager(redisCacheManager());
// 注入session manager
securityManager.setSessionManager(sessionManager());
return securityManager;
}
}
3、定义一个在线用户类😶
@Data
public class UserOnline implements Serializable
{
private static final long serialVersionUID = -8665498712823783978L;
private String sessionId;
private String userId;
private String username;
private String host;
private String ip;
private String status;
private Date startTime;
private Date lastTime;
private Long timeout;
}
4、获取在线用户接口 😧
@RestController
@RequestMapping("user")
public class IndexController {
@Autowired
private SessionDAO sessionDAO;
@RequestMapping("/userOnline/list")
@ResponseBody
public List<UserOnline> list() {
List<UserOnline> list = new ArrayList<>();
Collection<Session> sessions = sessionDAO.getActiveSessions();
for (Session session : sessions) {
UserOnline userOnline = new UserOnline();
UserInfoModel user = new UserInfoModel();
SimplePrincipalCollection principalCollection;
if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {
continue;
} else {
principalCollection = (SimplePrincipalCollection) session
.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
user = (UserInfoModel) principalCollection.getPrimaryPrincipal();
userOnline.setUsername(user.getUserName());
userOnline.setUserId(user.getUserId().toString());
}
userOnline.setSessionId((String) session.getId());
userOnline.setHost(session.getHost());
userOnline.setStartTime(session.getStartTimestamp());
userOnline.setLastTime(session.getLastAccessTime());
Long timeout = session.getTimeout();
if (timeout == 0L) {
userOnline.setStatus("离线");
} else {
userOnline.setStatus("在线");
}
userOnline.setTimeout(timeout);
list.add(userOnline);
}
return list;
}
}
访问接口获得Json数据
[
{
sessionId: "8e4813cb-24e0-4c5c-a2ea-fa62459386db",
userId: "30",
username: "吴军",
host: "0:0:0:0:0:0:0:1",
ip: null,
status: "在线",
startTime: 1652167812026,
lastTime: 1652167817938,
timeout: -1000
},
{
sessionId: "398c7caf-92f2-4af3-b506-ba631488af3d",
userId: "24",
username: "张三",
host: "127.0.0.1",
ip: null,
status: "在线",
startTime: 1652167804112,
lastTime: 1652167808655,
timeout: -1000
}
]
3、强制用户下线😬
@RequestMapping("/forceLogout")
@ResponseBody
public boolean forceLogout(String sessionId) {
Session session = sessionDAO.readSession(sessionId);
session.setTimeout(0);
return true;
}
最后:代码目前只是为了记录写在Controller里,实际可以根据自己的项目风格写在业务处理层中.