日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于shiro session失效报错问题

發布時間:2023/11/30 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于shiro session失效报错问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近做了一個項目,要用到shiro,做完之后發現有個異常經常發生org.apache.shiro.session.UnknownSessionException: There is no session with id?,經過多天的研究,終于得以解決


登錄的時候異常信息:

[java]?view plain?copy
  • org.apache.shiro.session.UnknownSessionException:?There?is?no?session?with?id?[4e8fe40a-6347-4c53-b273-829889656f6e]??
  • ????at?org.apache.shiro.session.mgt.eis.AbstractSessionDAO.readSession(AbstractSessionDAO.java:170)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSessionFromDataSource(DefaultSessionManager.java:236)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSession(DefaultSessionManager.java:222)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.session.mgt.AbstractValidatingSessionManager.doGetSession(AbstractValidatingSessionManager.java:118)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupSession(AbstractNativeSessionManager.java:108)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupRequiredSession(AbstractNativeSessionManager.java:112)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.session.mgt.AbstractNativeSessionManager.getAttribute(AbstractNativeSessionManager.java:209)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.session.mgt.DelegatingSession.getAttribute(DelegatingSession.java:141)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.subject.support.DelegatingSubject.getRunAsPrincipalsStack(DelegatingSubject.java:469)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.subject.support.DelegatingSubject.getPrincipals(DelegatingSubject.java:153)[251:org.apache.shiro.core:1.2.3]??
  • ????at?org.apache.shiro.subject.support.DelegatingSubject.getPrincipal(DelegatingSubject.java:149)[251:org.apache.shiro.core:1.2.3]??

  • 為何找不到呢,原因是這樣的。

    當用戶登錄的時候,web容器tomcat或者jetty會在線程池里面啟用線程調度,線程里面找到對應的servlet,shiro登錄的時候代碼如下

    [java]?view plain?copy
  • <span?style="white-space:pre">????</span>Subject?currentUser?=?SecurityUtils.getSubject();??
  • ??????????
  • ????????String?sessionId?=?"";??
  • ??
  • ????????if?(!currentUser.isAuthenticated())?{??
  • ??????????????UsernamePasswordToken?token?=?new?UsernamePasswordToken(username,?DigestUtils.md5Hex(passwd));??
  • ??????????????token.setRememberMe(true);??
  • ??????????????currentUser.login(token);??
  • ?????????}??

  • 方法SecurityUtils.getSubject()源碼是這樣

    [java]?view plain?copy
  • public?static?Subject?getSubject()?{??
  • ????????Subject?subject?=?ThreadContext.getSubject();??
  • ????????if?(subject?==?null)?{??
  • ????????????subject?=?(new?Subject.Builder()).buildSubject();??
  • ????????????ThreadContext.bind(subject);??
  • ????????}??
  • ????????return?subject;??
  • }??

  • 我們清楚的看到subject是從ThreadContext獲取,創建過就直接從里面獲取,沒有創建的話就重新創建一個subject,然后綁定到ThreadContext,調用subject獲取session的時候,他會去創建一個session,并且把session緩存起來,操作方法是在AbstractSessionDAO類里面,跟蹤得知這里放的是subject的代理對象。如果session超時時間設置過短的話,在用戶登錄的時候,隨著web容器分配的線程,很大的機會會分配之前的線程,而之前的線程綁定過了subject,subject沒有失效,subejct對象里面的session也沒有什么問題,但是session緩存里面的session失效了,用戶登錄的時候執行到currentuser.login(token)這個方法,他拿著之前的session,那后要去緩存里面讀取,但是已經失效了,所以會報上面那個異常。


    問題就是出現在這里,subject綁定到thread上下文里面,subject對象的session是個代理對象,正真的session是放在緩存里面,web容器隨機分配的線程有可能綁定過subject,一旦session失效,就會報錯。


    解決的辦法是在shiro去讀取session之前判斷有沒有失效,如果失效移除ThreadContext里面的subject,并且刪除緩存里面的session,代碼如下

    [java]?view plain?copy
  • @Override??
  • ????public?String?login(String?username,?String?passwd)?{??
  • ??????????
  • ????????Subject?currentUser?=?SecurityUtils.getSubject();??
  • ????????//提前1秒去判斷???防止這個if沒進??等執行下面的時候它卻失效了??<span?style="font-family:?Arial,?Helvetica,?sans-serif;">lengthenTimeOut是失效時間</span>??
  • ??
  • ????????if((System.currentTimeMillis()-currentUser.getSession().getStartTimestamp().getTime())>=lengthenTimeOut-1000){??
  • ????????????ThreadContext.remove(ThreadContext.SUBJECT_KEY);//移除線程里面的subject??
  • ????????????shiroSessionManager.getSessionDAO().delete(currentUser.getSession());//移除失效的session??
  • ????????????currentUser?=?SecurityUtils.getSubject();//重新獲取subject??
  • ????????}??
  • ??????????
  • ????????String?sessionId?=?"";??
  • [java]?view plain?copy
  • ????try?{??
  • ????????if?(!currentUser.isAuthenticated())?{??
  • ????????????UsernamePasswordToken?token?=?new?UsernamePasswordToken(username,?DigestUtils.md5Hex(passwd));??
  • ????????????token.setRememberMe(true);??
  • ????????????currentUser.login(token);??
  • ????????}??
  • ?????????
  • ????????sessionId?=?currentUser.getSession().getId().toString();??
  • ??????????
  • ??
  • ????}?catch?(ExcessiveAttemptsException?ex)?{??
  • ????????log.info(username?+?"帳號被鎖定1小時!",?ex);??
  • ????}?catch?(UnknownAccountException?uae)?{??
  • ????????log.info(username?+?"賬戶不存在!",?uae);??
  • ????}?catch?(IncorrectCredentialsException?ice)?{??
  • ????????log.info(username?+?"密碼不正確!",?ice);??
  • ????}?catch?(LockedAccountException?lae)?{??
  • ????????log.info(username?+?"賬戶被禁了!",?lae);??
  • ????}?catch?(AuthenticationException?ae)?{??
  • ????????log.info(username?+?"用戶名或密碼錯誤!",?ae);??
  • ????}?catch?(UnknownSessionException?ue)?{??
  • ????????log.info("登錄session失效"?+?sessionId,?ue);??
  • ??????????
  • ????}??
  • ??
  • ????log.info("登錄成功返回的sessionId+++++++++++++"?+?sessionId);??
  • ????return?sessionId;??
  • }??

  • 總結

    以上是生活随笔為你收集整理的关于shiro session失效报错问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。