我有一個使用Play Framework 2.3.4構建的系統,Ebean用於持久性。我想確保如果一個會話中已經過身份驗證的用戶再次登錄,他的其他會話將失效。如何防止玩家框架中的同一個帳戶進行多次登錄?
這會讓兩個人難以共享相同的帳戶。
Play中是否存在用於此類功能的常用模式?
我有一個使用Play Framework 2.3.4構建的系統,Ebean用於持久性。我想確保如果一個會話中已經過身份驗證的用戶再次登錄,他的其他會話將失效。如何防止玩家框架中的同一個帳戶進行多次登錄?
這會讓兩個人難以共享相同的帳戶。
Play中是否存在用於此類功能的常用模式?
我已經實現了一個解決方案,我堅持一個整數屬性,用戶名爲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;
}
}
我會有相同的方法,但具有唯一的標記 – silentprogrammer 2015-02-24 14:39:39
我選擇了整數,因爲不需要唯一性,因爲PLAY_SESSION cookie確保您無法欺騙它。它也計算登錄數量(這是非常有用的)。 – 2015-02-24 14:43:43
您使用的身份驗證系統是什麼? – 2015-02-24 13:39:56
我正在使用play.mvc.Security。我的實現只是將登錄用戶的電子郵件存儲在會話中。我目前正在爲此解決方案,我在會話中還存儲用戶和會話ID。 – 2015-02-24 13:50:36