spring boot apache shiro 获取在线用户和踢出用户
技术交流群:365814763
spring boot shiro 获取在线用户和踢出用户!
shiro工作图:
介绍:
subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。
securityManager:安全管理器,主体进行认证和授权都 是通过securityManager进行。它包含下面的认证器和授权器。
authenticator:认证器,主体进行认证最终通过authenticator进行的。
authorizer:授权器,主体进行授权最终通过authorizer进行的。
sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。可以实现单点登录。
SessionDao: 通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。
cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。
realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。(它的主要目的是与数据库打交道,查询数据库中的认证的信息(比如用户名和密码),查询授权的信息(比如权限的code等,所以这里可以理解为调用数据库查询一系列的信息,一般情况下在项目中采用自定义的realm,因为不同的业务需求不一样))
注意:在realm中存储授权和认证的逻辑。
写在前面,使用spring boot apache shiro获取在线用户和对在线用户进行管理,主要是通过EnterpriseCacheSessionDAO
的CRUD,知道了shrio操作用户的类就可以继承它,使用自己的CRUD操作用户了。
思路:
1、使用自己的类继承shiro默认的CRUD类EnterpriseCacheSessionDAO
2、设置bean sessionDAO
3、设置bean SessionManager 将sessionDAO配置到sessionManage
4、设置bean securityManager 将sessionManger配置到securityManager
/**
* <pre>
* 主要定义了在缓存中保存session,更新,删除,读取,获取所有的集合等操作。
* </pre>
* <small> 2018/12/24 | eriz</small>
*/
public class RedisSessionDAO extends EnterpriseCacheSessionDAO {
/**
* session 名称
*/
private String activeSessionsCacheName;
public RedisSessionDAO(String activeSessionsCacheName) {
this.activeSessionsCacheName = activeSessionsCacheName;
}
@Override
public String getActiveSessionsCacheName() {
return this.activeSessionsCacheName;
}
}
/**
* <pre>
*
* </pre>
* <small> 2018/12/24 | eriz</small>
*/
@Component
@ConfigurationProperties(prefix = "eriz.shiro")
public class ShiroProperties {
//自定义session名称,避免与tomcat或者其他session默认的名称重名
private String sessionKeyPrefix = "eriz:session";
private String jsessionidKey = "SESSION";
public String getSessionKeyPrefix() {
return sessionKeyPrefix;
}
public void setSessionKeyPrefix(String sessionKeyPrefix) {
this.sessionKeyPrefix = sessionKeyPrefix;
}
public String getJsessionidKey() {
return jsessionidKey;
}
public void setJsessionidKey(String jsessionidKey) {
this.jsessionidKey = jsessionidKey;
}
}
接下来是在shiroConfig类中配置sessionDAO与sessionManager、securityManager
/**
* 设置sessionDAO
* @param config
* @return
*/
@Bean
SessionDAO sessionDAO(ShiroProperties config){
RedisSessionDAO sessionDAO = new RedisSessionDAO(config.getSessionKeyPrefix());
return sessionDAO;
}
/**
* 设置sessionManager
* @param sessionDAO
* @return
*/
@Bean
public SessionManager sessionManager(SessionDAO sessionDAO) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
Collection<SessionListener> sessionListeners = new ArrayList<SessionListener>();
sessionListeners.add(new BDSessionListener());//这里的BDsessionListener实现了SessionListener接口,主要用于监听session的开始、停止与过期时间
sessionManager.setSessionListeners(sessionListeners);
sessionManager.setSessionDAO(sessionDAO);
return sessionManager;
}
/**
* 配置securityManager
* @param sessionManager
* @param authenticator
* @param authorizer
* @return
*/
@Bean("securityManager")
public DefaultWebSecurityManager getManager(SessionManager sessionManager,Authenticator authenticator,Authorizer authorizer) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
// 使用自己的realm
manager.setAuthenticator(authenticator);
manager.setAuthorizer(authorizer);
// manager.setCacheManager();
manager.setSessionManager(sessionManager);
return manager;
}
配置sessionDAO已经完成了,接下来测试获取数据
获取在线用户主要是Collection<Session> sessions = sessionDAO.getActiveSessions();
session中包含了id、host、lastAccesTime、startTimestamp、timeout等数据
@Autowired
private SessionDAO sessionDAO;
//获取在线用户信息
@Override
public List<OnlineDo> list() {
//数据量大时通过 page分页
Collection<Session> sessions = sessionDAO.getActiveSessions();
List<OnlineDo> list = new ArrayList<>();
for (Session session : sessions) {
if (session == null) continue;
OnlineDo onlineDo = new OnlineDo();
UserDo userDo = new UserDo();
//principalCollection 身份
SimplePrincipalCollection principalCollection = new SimplePrincipalCollection();
if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {
continue;
} else {
principalCollection = (SimplePrincipalCollection) session
.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
userDo = (UserDo) principalCollection.getPrimaryPrincipal();
onlineDo.setUsername(userDo.getUsername());
}
onlineDo.setId(session.getId().toString());
onlineDo.setHost(session.getHost());
onlineDo.setLastAccessTime(session.getLastAccessTime());
onlineDo.setStartTimestamp(session.getStartTimestamp());
onlineDo.setTimeout(session.getTimeout());
list.add(onlineDo);
}
return list;
}
//踢出用户
@Override
public boolean removeSession(String ids) {
//read session by id
Session session = sessionDAO.readSession(ids);//通过readSession读取session,然后调用delete删除
sessionDAO.delete(session);
return true;
}
整个获取在线用户和踢出用户已完成