Cookie/Session 是常見的狀態管理,Shiro提供了完整的企業級會話管理功能。 本文在上一篇文章Shiro功能應用(三)–EHCache緩存代碼基礎進行添加Session管理。
代碼實現:
代碼地址:
https://github.com/OooooOz/SpringBoot-Shiro
ShiroConfig的安全管理器SecurityManager:
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("shiroRealm") MyShiroRealm shiroRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm);
securityManager.setRememberMeManager(rememberMeManager()); //實現記住我
securityManager.setCacheManager(getEhCacheManager()); //實現緩存
securityManager.setSessionManager(sessionManager()); //session管理
return securityManager;
}
ShiroConfig的會話管理器sessionManager:
@Bean("sessionManager")
public SessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
Collection<SessionListener> listeners = new ArrayList<SessionListener>();
listeners.add(sessionListener()); //配置監聽
sessionManager.setSessionListeners(listeners);
sessionManager.setSessionIdCookie(sessionIdCookie());
sessionManager.setSessionDAO(sessionDAO());
sessionManager.setCacheManager(getEhCacheManager());
sessionManager.setGlobalSessionTimeout(10000); //全局會話超時時間(單位毫秒),默認30分鐘 暫時設置爲10秒鐘 用來測試
sessionManager.setDeleteInvalidSessions(true); //是否開啓刪除無效的session對象 默認爲true
// sessionManager.setSessionValidationSchedulerEnabled(true); //是否開啓定時調度器進行檢測過期session 默認爲true
//設置session失效的掃描時間, 清理用戶直接關閉瀏覽器造成的孤立會話 默認爲 1個小時
// sessionManager.setSessionValidationInterval(5000); //暫時設置爲 5秒 用來測試
sessionManager.setSessionIdUrlRewritingEnabled(false); //取消url 後面的 JSESSIONID
return sessionManager;
}
ShiroConfig的session監聽:
@Bean("sessionListener")
public ShiroSessionListener sessionListener(){
ShiroSessionListener sessionListener = new ShiroSessionListener();
return sessionListener;
}
ShiroConfig的SessionDAO:
@Bean
public SessionDAO sessionDAO() {
EnterpriseCacheSessionDAO enterpriseCacheSessionDAO = new EnterpriseCacheSessionDAO();
//使用ehCacheManager
enterpriseCacheSessionDAO.setCacheManager(getEhCacheManager());
//設置session緩存的名字 默認爲 shiro-activeSessionCache
enterpriseCacheSessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
//sessionId生成器
enterpriseCacheSessionDAO.setSessionIdGenerator(sessionIdGenerator());
return enterpriseCacheSessionDAO;
}
ShiroConfig的會話ID生成器:
@Bean
public SessionIdGenerator sessionIdGenerator() {
return new JavaUuidSessionIdGenerator();
}
ShiroConfig的會話管理的Cookie:
/**
* 查詢定義sessionId的cookie,防止與SERVLET容器的衝突,默認JSESSIONID
* 注意:這裏的cookie 不是上面的記住我 cookie 記住我需要一個cookie|session管理也需要自己的cookie
*/
@Bean("sessionIdCookie")
public SimpleCookie sessionIdCookie(){
SimpleCookie simpleCookie = new SimpleCookie("sid"); //cookie的名稱
simpleCookie.setHttpOnly(true); //設爲true後,只能通過http訪問,javascript無法訪問
simpleCookie.setPath("/");
simpleCookie.setMaxAge(-1); //maxAge=-1表示瀏覽器關閉時失效此Cookie
return simpleCookie;
}
Session監聽類:
package com.demo.config;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;
import java.util.concurrent.atomic.AtomicInteger;
public class ShiroSessionListener implements SessionListener{
/**
* 統計在線人數,juc包下線程安全自增
*/
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();
}
/**
* 獲取在線人數使用
* @return
*/
public AtomicInteger getSessionCount() {
return sessionCount;
}
}
控制器:
@RequestMapping("/userList.do")
public String userList(Model model){
//查詢所有的用戶信息並且顯示到頁面上
Subject subject = SecurityUtils.getSubject();
System.out.println("------是否通過認證:"+subject.isAuthenticated()+"------是否記住我:"+subject.isRemembered());
List<User> list = userService.findAll();
model.addAttribute("userList", list);
model.addAttribute("count",shiroSessionListener.getSessionCount());
return "userList";
}
頁面獲取在線人數
當前在線人數:'[[${count}]]'
功能測試:
訪問http://localhost:8080/userList.do登陸後,不關閉瀏覽器再次訪問改地址,是一樣可以訪問的,Web容器的Session一般默認30min才失效。
本例中設置sessionManager.setGlobalSessionTimeout(10000); 也就是Shiro管理的session10秒後失效,所以登陸後頁面不作任何操作,10s後再訪問,session失效則需重新登陸。
會話監聽器實現SessionListener接口,頁面能夠獲取統計的在線人數,