閱讀768 返回首頁    go 阿裏雲 go 技術社區[雲棲]


關於Shiro登陸退出遇到的一些問題

寫在開始

最近項目中出現一些問題,以前可能不大關注,但是問題是實實在在存在的。

3558453205

問題一

係統重啟用戶登陸或者退出報錯: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的原理導致的,所以大家使用開源框架的時候一定要弄清楚其原理,這樣才可以精確的定位問題。

小站:https://blog.52itstyle.com

最後更新:2017-04-24 21:32:59

  上一篇:go 雲計算網絡基礎架構的實踐和演進——打造雲計算網絡基石
  下一篇:go Java代理機製