2015-02-24 37 views
1

我有一個使用Play Framework 2.3.4構建的系統,Ebean用於持久性。我想確保如果一個會話中已經過身份驗證的用戶再次登錄,他的其他會話將失效。如何防止玩家框架中的同一個帳戶進行多次登錄?

這會讓兩個人難以共享相同的帳戶。

Play中是否存在用於此類功能的常用模式?

+0

您使用的身份驗證系統是什麼? – 2015-02-24 13:39:56

+0

我正在使用play.mvc.Security。我的實現只是將登錄用戶的電子郵件存儲在會話中。我目前正在爲此解決方案,我在會話中還存儲用戶和會話ID。 – 2015-02-24 13:50:36

回答

0

我已經實現了一個解決方案,我堅持一個整數屬性,用戶名爲sessionCounter。每次用戶進行身份驗證時(如提供用戶名密碼),這個值都會增加,並存儲在用戶記錄和新會話中。

每次使用現有會話訪問系統時,都會將其與會話計數器進行比較,如果會話的值低於DB中會話無效的值。

這裏是身份驗證methood:

/** 
* Handle login form submission. 
*/ 
public static Result authenticate() { 
    Form<Login> loginForm = form(Login.class).bindFromRequest(); 
    if(loginForm.hasErrors()) { 
     return badRequest(login.render(loginForm)); 
    } else { 
     User user = loginForm.get().user; 
     session().clear(); 
     session("username", user.getEmail()); 
     session("counter", ""+user.incrementSessionCounter()); 
     user.setLastLoginDate(new Date()); 
     user.save(); 

下面是play.mvc.Security.Authenticator實現:

@Override 
public String getUsername(Http.Context context) { 
    final User user; 
    if (!context.args.containsKey("user")) { 
     user = ExtranetUser.findByEmail(context.session().get("username")); 
     context.args.put("user", user); 
    } else { 
     user = (User) context.args.get("user"); 
    } 
    if(user != null){ 
     final String counterStr = context.session().get("counter"); 
     if (user.getSessionCounter() > NumberUtils.toInt(counterStr, 0)) { 
      Logger.debug("Session invalidated for " + user + " had session " + counterStr + " but latest session is " + user.getSessionCounter()); 
      context.flash().put("session", "user.duplicateSession"); 
      context.session().clear(); 
      return null; // results in redirect to login page with flash 
     } 
     return user.getEmail(); 
    } else { 
     return null; 
    } 
} 
+0

我會有相同的方法,但具有唯一的標記 – silentprogrammer 2015-02-24 14:39:39

+1

我選擇了整數,因爲不需要唯一性,因爲PLAY_SESSION cookie確保您無法欺騙它。它也計算登錄數量(這是非常有用的)。 – 2015-02-24 14:43:43

相關問題