一 概要
Shiro提供了完整的企業(yè)級會話管理功能,不依賴于底層容器(如Tomcat)赋续,不管是J2SE還是J2EE環(huán)境都可以使用干奢,提供了會話管理,會話事件監(jiān)聽糯彬,會話存儲/持久化凭语,容器無關(guān)的集群,失效/過期支持撩扒,對Web的透明支持似扔,SSO單點登錄的支持等特性吨些。即直接使用 Shiro 的會話管理可以直接替換如 Web 容器的會話管理。
shiro-redis開源項目已經(jīng)很好的將shiro與redis整合到一起炒辉,實現(xiàn)了將session存入redis豪墅,可以方便的用于session共享實現(xiàn)集群部署。
主要涉及到緩存跟session的配置
二 使用步驟
導(dǎo)入依賴
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="xml" cid="n9" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.2.3</version>
</dependency></pre>
配置會話管理器
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n11" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">//session管理
@Bean
public SessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
Collection<SessionListener> listeners = new ArrayList<SessionListener>();
listeners.add(new ShiroSessionListener());
// 配置自定義監(jiān)聽,比如統(tǒng)計網(wǎng)站在線人數(shù)等
sessionManager.setSessionListeners(listeners);
//設(shè)置redisSessionDao
sessionManager.setSessionDAO(redisSessionDAO());
//設(shè)置session超時時間為1小時(單位毫秒)
//sessionManager.setGlobalSessionTimeout(3600000);
sessionManager.setGlobalSessionTimeout(-1);//永不超時
return sessionManager;
}</pre>
配置Reids緩存管理器
將緩存信息保存到Redis中
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n15" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">@Bean
public RedisCacheManager cacheManager(){
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
//redis中針對不同用戶緩存
redisCacheManager.setPrincipalIdFieldName("username");
//用戶權(quán)限信息緩存時間
redisCacheManager.setExpire(200000);
return redisCacheManager;
}</pre>
配置RedisSessionDAO
SessionDAO的作用是為Session提供CRUD并進行持久化的一個shiro組件
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n19" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">@Bean
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
return redisSessionDAO;
}</pre>
配置RedisCacheManager
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n21" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">//配置cacheManager
public RedisCacheManager cacheManager(RedisManager redisManager) {
RedisCacheManager redisCacheManager = new RedisCacheManager();
//redis中針對不同用戶緩存
redisCacheManager.setPrincipalIdFieldName("username");
//用戶權(quán)限信息緩存時間
redisCacheManager.setExpire(200000);
redisCacheManager.setRedisManager(redisManager);
return redisCacheManager;
}</pre>
配置redisManager
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n23" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(host);
redisManager.setPort(port);
redisManager.setTimeout(timeout);
redisManager.setPassword(password);
redisManager.setExpire(3600);//配置緩存過期時間(秒)
return redisManager;
}</pre>
配置緩存認(rèn)證信息
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n25" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">@Bean
public UserRealm realm(HashedCredentialsMatcher hashedCredentialsMatcher) {
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(hashedCredentialsMatcher);
userRealm.setCachingEnabled(true);
//啟用身份驗證緩存黔寇,即緩存AuthenticationInfo信息偶器,默認(rèn)false
userRealm.setAuthenticationCachingEnabled(true);
//緩存AuthenticationInfo信息的緩存名稱
userRealm.setAuthenticationCacheName("authenticationCache");
//啟用授權(quán)緩存,即緩存AuthorizationInfo信息缝裤,默認(rèn)false
userRealm.setAuthorizationCachingEnabled(true);
//緩存AuthorizationInfo信息的緩存名稱
userRealm.setAuthorizationCacheName("authorizationCache");
return userRealm;
}</pre>
配置會話ID生成器
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n27" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">@Bean
public SessionIdGenerator sessionIdGenerator() {
return new JavaUuidSessionIdGenerator();
} </pre>
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n29" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public class ShiroSessionListener implements SessionListener{
/**
* 統(tǒng)計在線人數(shù)
*/
private final AtomicInteger sessionCount = new AtomicInteger(0);
/**
* 會話創(chuàng)建時觸發(fā)
* @param session
*/
@Override
public void onStart(Session session) {
//會話創(chuàng)建屏轰,在線人數(shù)加一
sessionCount.incrementAndGet();
}
/**
* 退出會話時觸發(fā)
* @param session
*/
@Override
public void onStop(Session session) {
//會話退出,在線人數(shù)減一
sessionCount.decrementAndGet();
}
/**
* 會話過期時觸發(fā)
* @param session
*/
@Override
public void onExpiration(Session session) {
//會話過期,在線人數(shù)減一
sessionCount.decrementAndGet();
}
/**
* 獲取在線人數(shù)使用
* @return
*/
public AtomicInteger getSessionCount() {
return sessionCount;
}
}</pre>