關於Shiro登陸退出遇到的一些問題
寫在開始
最近項目中出現一些問題,以前可能不大關注,但是問題是實實在在存在的。
問題一
係統重啟用戶登陸或者退出報錯:Disk Write of 407a1347-c2c6-434e-89e3-365aa277497c failed
這個問題,並不是經常出現,看詳細錯誤信息,應該是數據 list或者map序列化的問題。看了一下實體類都實現了序列化。
解決方案
突然想起,以前是沒有這個問題的,自從升級了Ehcache的jar包,這個問題時常出現。目前使用的是ehcache2.10.0,隨後版本降級為ehcache2.6.9,重啟以後再沒出現過這個問題。
問題二
用戶退出無法請求到logout.action,導致盡管session已經清理,但是用戶緩存信息還是實實在在存在的。
如果把logout 改為user或者anon,會報以下錯誤:
java.lang.IllegalStateException: org.apache.shiro.session.UnknownSessionException: There is no session with id [1370262d-eeac-4ee7-a86e-1a2b14c86d83]
字麵意思是,找不到session,的確F12 sid已經不見了,shiro在做跳轉的時候就報這個錯誤(目前不清楚原因,但是後麵有解決方案)
部分代碼:
<!-- Shiro權限過濾過濾器定義 -->
<property name="filterChainDefinitions">
<value>
/common/** = anon
/template/** = anon
/LoginAction_login.action = anon
/LoginAction_logout.action = logout
/** =user
</value>
</property>
仔細膜拜一下源代碼,退出操作是走LogoutFilter過濾的。
部分代碼:
protected boolean preHandle(ServletRequest request, ServletResponse response)
throws Exception {
Subject subject = getSubject(request, response);
String redirectUrl = getRedirectUrl(request, response, subject);
try {
subject.logout();
} catch (SessionException ise) {
log.debug(
"Encountered session exception during logout. This can generally safely be ignored.",
ise);
}
issueRedirect(request, response, redirectUrl);
return false;
}
注意:最後的return false,返回false表示不執行後續的過濾器,直接返回跳轉到登錄頁麵。所以也就不可能再請求到LoginAction_logout.action,也就不會清空用戶緩存信息了。
解決方案
重寫LogoutFilter:
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import com.acts.web.sys.utils.UserUtils;
/**
* 重寫退出過濾器
* 創建者 張誌朋
* 創建時間 2017年4月24日
*/
public class SystemLogoutFilter extends LogoutFilter {
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
Subject subject = getSubject(request, response);
String redirectUrl = getRedirectUrl(request, response, subject);
try {
//清空緩存
UserUtils.clearCache();
subject.logout();
} catch (SessionException e) {
e.printStackTrace();
}
issueRedirect(request, response, redirectUrl);
return false;
}
}
配置文件定義:
<bean />
<!-- 加入filters -->
<property name="filters">
<map>
<entry key="logout" value-ref="kickoutSessionControlFilter"/>
</map>
</property>
如果存在多realm,可能會返回不同的登陸頁,這裏可以把return false 改為 return true 執行後續的過濾器,自定義Action重定向不同的頁麵。
好,到這兩個問題都解決了。第二個問題,基本就是由於未理解shiro的原理導致的,所以大家使用開源框架的時候一定要弄清楚其原理,這樣才可以精確的定位問題。
最後更新:2017-04-24 21:32:59