小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

spring security3.0控制多個用戶賬號同時登錄和管理員踢出用戶(原創(chuàng)) - ...

 wangxq 2011-03-24
 聲明一下,這篇文章不是基于acegi  spring security2.0寫的,  我發(fā)現(xiàn)很多文章都是基于老版本寫的,  并不適用最新版。
下面跟大家分享一下在spring security3.0里如何正宗的做法達到控制多個賬號請求的經驗。
步驟1
view plaincopy to clipboardprint?
<http auto-config="true" > 
 
!--session-fixation-protection="none" 防止偽造sessionid攻擊. 用戶登錄成功后會銷毀用戶當前的session.創(chuàng)建新的session,并把用戶信息復制到新session中.--> 
    <session-management invalid-session-url="/common/login.jsp?invalid-session=true" > 
     <concurrency-control error-if-maximum-exceeded="true" max-sessions="1" /> 
 
</http> 
    <http auto-config="true" >
<!--session-fixation-protection="none" 防止偽造sessionid攻擊. 用戶登錄成功后會銷毀用戶當前的session.創(chuàng)建新的session,并把用戶信息復制到新session中.-->
        <session-management invalid-session-url="/common/login.jsp?invalid-session=true" >
         <concurrency-control error-if-maximum-exceeded="true" max-sessions="1" />
    </http>
下面只貼出關鍵部分, 為了不影響閱讀。
注意: 不需要配置 SessionRegistry 等bean( 假設你其他地方不用到的話, 如果用到需要在
<concurrency-control session-registry-ref="sessionRegistry" error-if-maximum-exceeded="true" max-sessions="1" />
加上一個屬性
在做某個管理員踢出一個賬號的時候, SessionRegistry 這個bean是需要用到的。 寫法如下:
view plaincopy to clipboardprint?
@RequestMapping(value = "logout.html")  
public String logout(String sessionId, String sessionRegistryId, String name, HttpServletRequest request, ModelMap model){    
    List<Object> userList=sessionRegistry.getAllPrincipals();  
    for(int i=0; i<userList.size(); i++){  
        User userTemp=(User) userList.get(i);      
        if(userTemp.getName().equals(name)){          
            List<SessionInformation> sessionInformationList = sessionRegistry.getAllSessions(userTemp, false);  
            if (sessionInformationList!=null) {   
                for (int j=0; j<sessionInformationList.size(); j++) {  
                    sessionInformationList.get(j).expireNow();  
                    sessionRegistry.removeSessionInformation(sessionInformationList.get(j).getSessionId());  
                    String remark=userTemp.getName()+"被管理員"+SecurityHolder.getUsername()+"踢出";  
                    loginLogService.logoutLog(userTemp, sessionId, remark);     //記錄注銷日志和減少在線用戶1個  
                    logger.info(userTemp.getId()+"  "+userTemp.getName()+"用戶會話銷毀," + remark);  
                }  
            }  
        }  
    }  
    return "auth/onlineUser/onlineUserList.html";  

 @RequestMapping(value = "logout.html")
 public String logout(String sessionId, String sessionRegistryId, String name, HttpServletRequest request, ModelMap model){ 
  List<Object> userList=sessionRegistry.getAllPrincipals();
  for(int i=0; i<userList.size(); i++){
   User userTemp=(User) userList.get(i); 
   if(userTemp.getName().equals(name)){  
    List<SessionInformation> sessionInformationList = sessionRegistry.getAllSessions(userTemp, false);
    if (sessionInformationList!=null) {
     for (int j=0; j<sessionInformationList.size(); j++) {
      sessionInformationList.get(j).expireNow();
      sessionRegistry.removeSessionInformation(sessionInformationList.get(j).getSessionId());
      String remark=userTemp.getName()+"被管理員"+SecurityHolder.getUsername()+"踢出";
      loginLogService.logoutLog(userTemp, sessionId, remark);  //記錄注銷日志和減少在線用戶1個
      logger.info(userTemp.getId()+" "+userTemp.getName()+"用戶會話銷毀," + remark);
     }
    }
   }
  }
  return "auth/onlineUser/onlineUserList.html";
 }
有時候按文檔和網上配置出來是很華麗, 可事實有時候就是沒有如期運行。
我打開火狐  360瀏覽器, 還是等兩個賬號同時登錄。
無奈之下把源碼下下載剖析(常干的事兒, 喜歡搗騰這些東西)
判斷重復的類是ConcurrentSessionControlStrategy.java下的
checkAuthenticationAllowed這個函數的
view plaincopy to clipboardprint?
final List<SessionInformation> sessions = sessionRegistry.getAllSessions(authentication.getPrincipal(), false);  
 
int sessionCount = sessions.size(); 
        final List<SessionInformation> sessions = sessionRegistry.getAllSessions(authentication.getPrincipal(), false);
        int sessionCount = sessions.size();
最重要的一句話是:
sessionInformationList.get(j).expireNow();
這句強制T出了用戶, (設置為過期)
如果想徹底刪除, 加上
sessionRegistry.removeSessionInformation(sessionInformationList.get(j).getSessionId());
即可,
這樣使用getAllPrincipals  則獲取不到被T出的用戶了,  其實原理不是直接刪除User對象, 只結束了它的sessionId,
因為這個User可能不止對應著1個sessionId
我發(fā)現(xiàn), 無論我怎么配置,  sessionCount老是煩人的 0。    即使我手動配置了ConcurrentSessionControlStrategy這個bean也沒用(默認會自己調的)
無奈中想自己寫一個自定義的計數器控制, 但細想它這東西不至于這個小問題都出這么大的漏洞吧?
現(xiàn)在的問題是:
如何讓 int sessionCount = sessions.size();  這句在第二個賬號登陸的時候不為0。
于是我進入了sessionRegistry.getAllSessions(authentication.getPrincipal(), false);  這個函數。
也就是SessionRegistryImpl.java
    public List<SessionInformation> getAllSessions(Object principal, boolean includeExpiredSessions) {
        final Set<String> sessionsUsedByPrincipal = principals.get(principal);
這個函數是通過在一個HashMap里拿到key value的。
而principals的聲明這樣寫。
private final Map<Object,Set<String>> principals = Collections.synchronizedMap(new HashMap<Object,Set<String>>());
現(xiàn)在的問題變?yōu)榱耍?/div>
如何讓兩個principal  ,  也就是User, 也就是
public UserDetails loadUserByUsername(String username)
兩次登陸的時候返回的是同一個對象。
那么如何做到兩次在不同瀏覽器登陸的時候返回的是同一個User?
答案是java的基礎, equal   hashcode方法重寫。
在User對象里添加以下方法:
view plaincopy to clipboardprint?
public boolean equals(Object object) {  
    if (object instanceof BaseObject) {  
        if (this.id.equals(((BaseObject) object).getId()))  
            return true;  
    }  
    return false;  
}  
 
   public int hashCode(){       
       return this.id.hashCode();       
   }    
 public boolean equals(Object object) {
  if (object instanceof BaseObject) {
   if (this.id.equals(((BaseObject) object).getId()))
    return true;
  }
  return false;
 }
 
    public int hashCode(){    
        return this.id.hashCode();    
    }   
我就不浪費CSDN的硬盤空間了, 不過還是得貼出最后一句話:
HashMap的key判斷key是否相等也是從hashcode和equals是否相等判斷
 從上面可以看出, 我們之前登陸的用戶是存在    Map<Object,Set<String>> principals  的。
這個存儲結構是,  一個User  對應多個Set集合的sessionId。
所以要判斷用戶是否已存在登陸的了, 當然要重寫這2個方法。
 
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/sinlff/archive/2010/09/18/5892531.aspx

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多