無憂無鹵

          鳥在籠中,恨關(guān)羽不能張飛;人處世上,要八戒更需悟空

          定制的Spring Security(Acegi)的并發(fā)會話過濾器(ConcurrentSessionFilter)的編碼過程(轉(zhuǎn))

          定制的Spring Security(Acegi)的并發(fā)會話過濾器(ConcurrentSessionFilter)的編碼過程

          上一帖述及使用ConcurrentSessionFilter限制同帳號登錄多次的方法,同帳號多次登錄限制是運(yùn)行系統(tǒng)必需的功能,所以作者對其深入測試,在上一帖中也列舉了Spring Security的ConcurrentSessionFilter和ConcurrentSessionControllerImpl類的幾個(gè)限制。做一下簡單的總結(jié),下面假設(shè)同時(shí)使用DigestProcessingFilter和輔助類:

          • 如果exceptionIfMaximumExceeded = true,即第二個(gè)發(fā)起的會話被禁止,如果一個(gè)用戶重新啟動(dòng)瀏覽器,再次登錄失敗,因?yàn)榍耙粋€(gè)會話沒有超時(shí),被當(dāng)成了多次登錄。
          • 如果exceptionIfMaximumExceeded = false,如果兩個(gè)人使用同一個(gè)帳號登錄,將出現(xiàn)交互將對方踢出去的現(xiàn)象,實(shí)際上并沒有禁止任何人登錄,只是每次要先將另一個(gè)人踢下去。


          需求

          我想使用exceptionIfMaximumExceeded = true,同時(shí)允許同一個(gè)用戶在同一臺機(jī)器上連續(xù)登錄多次,我采取了編寫定制的ConcurrentSessionController實(shí)現(xiàn)類的方法。



          原理

          ConcurrentSessionController是一個(gè)接口,有兩個(gè)需要實(shí)現(xiàn)的方法:checkAuthenticationAllowed()和registerSuccessfulAuthentication(),Spring Security提供了一個(gè)實(shí)現(xiàn)類ConcurrentSessionControllerImpl,經(jīng)過分析缺省的實(shí)現(xiàn)類,發(fā)現(xiàn)方法allowableSessionsExceeded()處理多次并發(fā)會話,在SecurityRegistry中保存每個(gè)會話的信息,主要是用戶帳號對應(yīng)的會話ID(sessionId)和最后發(fā)起時(shí)間,在并發(fā)發(fā)生時(shí),從SecurityRegistry中取出關(guān)于某個(gè)用戶帳號的所有會話,如果exceptionIfMaximumExceeded = false,找到最早一個(gè)會話,將其釋放掉,騰出空間給新會話,如果exceptionIfMaximumExceeded = true,將發(fā)出一個(gè)異常。

          所以,需要改進(jìn)allowableSessionsExceeded(),如果exceptionIfMaximumExceeded = true讓程序判斷客戶地址,如果同一個(gè)IP,則允許登錄,將最早的會話釋放掉,如果不是同一個(gè)IP在發(fā)出異常。

          在SecurityRegistry中,用戶帳號信息存在一個(gè)對象中,名字是principal,當(dāng)前是一個(gè)Object對象,實(shí)際上只是存了一個(gè)字符串,所以需要擴(kuò)展principal,寫一個(gè)定制的類(我的類含有兩個(gè)屬性:username和userip),里面保存客戶IP信息。allowableSessionsExceeded()只是使用SecurityRegistry,SecurityRegistry中的內(nèi)容是由registerSuccessfulAuthentication()方法寫入的,所以,在該方法中需要將原來的pricipal對象替換成定制的Principal類的對象。同時(shí)checkAuthenticationAllowed()方法也要修改,因?yàn)檫@個(gè)方法要查詢SecurityRegistry,查詢條件替換成定制的Principal類的對象。



          注意事項(xiàng)

          定制的Principal類要實(shí)現(xiàn)equals()和hashCode()和toString()三個(gè)方法,在equals()方法中只要username相同就表示兩個(gè)對象相同,而在hashCode()中只需要將username的hashcode計(jì)算在內(nèi),因?yàn)镾ecurityRegistry是以principal為關(guān)鍵字的Map容器,這兩個(gè)方法決定了對Map的查詢。toString()方法可以根據(jù)自己的需要寫,我只是將username輸出。



          測試

          將定制的ConcurrentSessionController對象編制(wire)到應(yīng)用系統(tǒng)中,經(jīng)過測試,能夠達(dá)到預(yù)想目的。



          存在的問題

          原來想省點(diǎn)勁,只要繼承ConcurrentSessionControllerImpl并重載上述三個(gè)方法就行了,但是不知道為什么securityRegistery屬性一直注入不了,一氣之下,寫了一個(gè)直接實(shí)現(xiàn)ConcurrentSessionController接口的新類。實(shí)際上也不是從頭寫,將ConcurrentSessionControllerImpl代碼改吧該吧即可,用不了幾分鐘,這就是開源的好處。



              轉(zhuǎn)自 http://www.gooseeker.com/cn/node/517

          posted on 2009-05-08 10:33 beyond 閱讀(3318) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           

          導(dǎo)航

          <2009年5月>
          262728293012
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          統(tǒng)計(jì)

          常用鏈接

          留言簿(1)

          隨筆檔案

          相冊

          搜索

          最新評論

          • 1.?re: 近期任務(wù)
          • 大哥 等著你的drools5翻譯呢 drools4把我搞死了 如果你有關(guān)于drools4的心得的話請指教 感覺自己使用的不是很好 望賜教 QQ:53816565 謝謝
          • --sunnidy
          • 2.?re: Mysql遷移到Oracle
          • 不錯(cuò),看樣子支持大多數(shù)數(shù)據(jù)庫遷移到oracle,不知道是否支持從oracle轉(zhuǎn)出?
          • --FastUnit

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 通州区| 汨罗市| 广汉市| 乌拉特前旗| 方城县| 阿荣旗| 石渠县| 云林县| 绥中县| 安达市| 延安市| 桐庐县| 兴化市| 建德市| 扎兰屯市| 曲周县| 北票市| 曲麻莱县| 福海县| 香格里拉县| 延川县| 临颍县| 兴隆县| 武功县| 兴化市| 西和县| 崇左市| 天祝| 亳州市| 莎车县| 明溪县| 吴忠市| 开原市| 揭西县| 漯河市| 沙洋县| 嘉义市| 晋城| 大埔县| 万州区| 上思县|