2014-12-05 36 views
0

我學習以下實施「記住我」功能,登錄問題:http://varuntayur.wordpress.com/2012/01/25/session-management-in-gwt/「記住我」與會話ID返回給客戶端

我不過大部分的工作,而我的道歉這可能是。非常基本的,我有困難的會話ID返回給客戶端

我的服務器端代碼:

到數據庫的調用,以驗證用戶並返回信息:

public Account authenticateAccount(String accountName, String pass) { 

     Account account = null; // necessary unless you do something in the exception handler 
     String stored_hash = null; 
     PreparedStatement ps = null; 

     // Create connection/statement variables outside of try block 
     Connection c = null; 

     String selectQry = ("SELECT acc_id, grp_id, acc_password, acc_level, acc_enabled, acc_archived " + 
          "FROM at_accounts " + 
          "WHERE acc_email_address = ?;"); 

     try { 
      // Get Connection and Statement from DataSource 
      c = ds.getConnection(); 
      ps = c.prepareStatement(selectQry); 

      try { 
       // Create a statement and execute the query on it   
       ps.setString(1, accountName); 

       // Get result set 
       ResultSet result = ps.executeQuery(); 

       while (result.next()) { 
        account = new Account(result.getString(1), result.getString(2), null, result.getString(3), 
        result.getString(4), null, result.getInt(5), result.getDate(6), null); 

        stored_hash = result.getString(3); 
       } 

       // Clean up 
       ps.close(); 
       c.close(); 

      } catch (SQLException se) { 
       System.out.println("SQLException occurred in authenticateAccount: " + se.toString()); 
      } catch (Exception e) { 
       System.out.println("Errors occurred in authenticateAccount: " + e.toString()); 
      } 


     } catch (SQLException e1) { 
      System.out.println("SQLException occurred in authenticateAccount: " + e1.toString()); 
      e1.printStackTrace(); 
     } finally { 

      // Ensure connection is closed and returned to the pool, even if errors occur. 
      // This is *very* important if using a connection pool, because after all the 
      // connections are used, the application will hang on getConnection(), waiting 
      // for a connection to become available. 
      // Any errors from the following closes are just ignored. The main thing is 
      // that we have definitely closed the connection. 
      try { if(ps != null) ps.close(); } catch (Exception e) {} 
      try { if(c != null) c.close(); } catch (Exception e) {} 
     } 
     // Done 

     //Check that the hashed value of the password equals the stored hashed value 
     //If it does not then account will be set to null. 
     if (stored_hash != null) { 
      if (BCrypt.checkpw(pass, stored_hash)) { 
      } else { 
       account = null; 
      } 
     } else { 
      account = null; 
     } 

     storeUserInSession(account); 
     return account; 
    } 

的代碼來存儲會話ID

private void storeUserInSession(Account account) 
{ 
    HttpServletRequest httpServletRequest = this.getThreadLocalRequest(); 
    HttpSession session = httpServletRequest.getSession(true); 
    session.setAttribute("account", account); 
    System.out.println("storeUserInSession: " + account); 
} 

中的println返回: 「storeUserInSession:[email protected]」。

當這個被返回到我使用下面的代碼來獲取會話ID和創建cookie中的客戶端:

//Remember the Login 
String sessionID = account.getSessionId(); 
Window.alert("Session ID = " + sessionID); 
final long DURATION = 1000 * 60 * 60 * 24 * 14; //duration remembering login. 2 weeks in this example. 
Date expires = new Date(System.currentTimeMillis() + DURATION); 
Cookies.setCookie("sid", sessionID, expires, null, "/", false); 

的Window.alert顯示account.getSessionId()爲空(所有其他帳戶信息正確返回,例如訪問級別(用戶,管理員等))。

感謝您的任何幫助。

問候,

格林

回答

0

的問題是,你永遠不會設置的SessionID在account對象,所以它總是null

編輯:移動storeUserInSession到如果從句,所以其唯一存儲如果帳戶數據有效
要做到這一點,你可以做這樣的事情:

public Account authenticateAccount(String accountName, String pass) { 
    //....Code... 
    if (stored_hash != null) { 
     if (BCrypt.checkpw(pass, stored_hash)) { 
     //Before returning the account you have to set the sessionID for the account 
      account = storeUserInSession(account); 
     } else { 
      account = null; 
     } 
    } else { 
     account = null; 
    } 
    return account; 
} 

然後改變storeUserInSession(account)返回類型來account並設置會話ID有

private Account storeUserInSession(Account account) 
{ 
    HttpServletRequest httpServletRequest = this.getThreadLocalRequest(); 
    HttpSession session = httpServletRequest.getSession(true); 
    //here you store the sessionID in account 
    account.setSessionId(session.getId()); 
    session.setAttribute("account", account); 
    return account; 
} 

編輯: 的解釋登錄如何在這裏工作:

  1. 在登錄檢查,如果用戶數據是有效的。
    你這樣做是authenticateAccount()
  2. 如果登錄是有效的,你爲該用戶創建一個新的會話,並添加accountData本屆會議
    HttpSession session = httpServletRequest.getSession(true)
    session.setAttribute("account", account);
  3. 在客戶端添加一個Cookie,是有效的直到某個日期,然後將用戶轉發到您的受保護頁面。
    Cookies.setCookie("sid", sessionID, expires)
  4. 當用戶返回到您的頁面時,您檢查是否有名爲「sid」的cookie。 請記住,這是而不是驗證用戶,這是稍後在服務器端完成的。這裏只是檢查用戶是否以前登錄過。

    public void onModuleLoad() 
    { //user was logged in before?(the Stringname "sessionID" is a little bit irritating here 
    String sessionID = Cookies.getCookie("sid"); 
    //no? then just show the loginWindow 
    if (sessionID == null) 
    { 
        displayLoginWindow(); 
    } else 
    { //yes?then check if there is a valid session for him 
        checkWithServerIfSessionIdIsStillLegal(); 
    } 
    

    }

  5. 在服務器端,你現在檢查會話是否仍然有效。你可以這樣做,不用在cookie中存儲任何sessionID,因爲你得到的實際會話是HttpSession session = httpServletRequest.getSession()。這裏的要點是你不要檢查sessionID是否匹配,但是如果在這個會話中存儲了任何賬戶(看點2)。如果不是那麼它存儲帳戶數據的明顯不同的會話,並且用戶必須再次登錄。

    Object accountObj = session.getAttribute("account"); 
         if (accountObj != null && accountObj instanceof Account) 
         { 
           account = (Account) accountObj; 
         }` 
    

我希望這是寄託都有點更加清晰,表明你不必須的SessionID存儲在cookie中。

+0

嗨@Tobika,我做了這個改變和「String sessionID = account.getSessionId();」仍然返回null。在我看來,我應該調用「storeUserInSession(account);」在我在while循環中加載帳戶詳細信息之前,我可以將其與其他詳細信息一起返回。然而,那麼我需要用一個字符串(即,accountName)來調用「storeUserInSession」。這是否有效?謝謝你的幫助。問候,Glyn – Glyn 2014-12-10 00:17:36

+0

嗨@Tobika,我試着用「sessionID = storeUserInSession(accountName);」在try語句之前幷包含「sessionID」代替最後一個「null」(即account = new Account(result.getString(1),result.getString(2),null,result.getString(3), \t \t \t \t result.getString(4),null,result.getInt(5),result.getDate(6),sessionID);)。但是,這只是將客戶名稱返回給客戶端,這對我來說似乎並不安全。這是應該如何工作?如果是的話,是否有更好的方法來做到這一點?問候,Glyn – Glyn 2014-12-10 00:51:47

+0

@Glyn嘿,我編輯我的帖子來解釋登錄更好一點...我希望這可以幫助 – Tobika 2014-12-10 08:57:42