Created
February 21, 2012 21:01
-
-
Save ahmetb/1878904 to your computer and use it in GitHub Desktop.
play secure module alternative
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package controllers; | |
import models.User; | |
import play.Logger; | |
import play.Play; | |
import play.libs.Crypto; | |
import play.mvc.Before; | |
import play.mvc.Controller; | |
import play.mvc.Http; | |
import play.mvc.Scope; | |
import play.mvc.Http.Request; | |
import play.mvc.Http.Response; | |
import service.FriendshipService; | |
import service.UserService; | |
/** | |
* Authentication and privileges check for web interface. | |
* | |
* @author ahmet alp balkan <ahmetalpbalkan at gmail.com> | |
*/ | |
public class Security extends Controller { | |
private static final String REMEMBER_ME_COOKIE_KEY = "rememberme"; | |
private static final String USER_ID_SESSION_KEY = "id"; | |
/** | |
* Sends data about the status of the current user to the flash scope to be | |
* used in templates. | |
*/ | |
@Before(unless = "signOut", priority = 0) | |
static void bindSecurityData() { | |
if (isConnected() && !request.url.toLowerCase().contains("logout")) { | |
User u = connectedUser(); | |
if (u == null) | |
Account.signOut(); | |
flash.put("connected", true); | |
// bind other flash scope params here for logined users. | |
} | |
} | |
/** | |
* log ins the user before the actual controller intercepts the request if | |
* the user is not connected. | |
*/ | |
@Before(unless = { "signOut" }, priority = 5) | |
static void rememberMeHook() { | |
if (!isConnected()) | |
useRememberMe(request); | |
} | |
/** | |
* Checks for login and remember-me cookie. If authentication is invalid | |
* then redirects to sign-in page. | |
*/ | |
static void checkAuthenticated() { | |
if (!isConnected() && useRememberMe(request) == false) { | |
Account.signIn(request.url); | |
} | |
} | |
/** | |
* Checks specific authenticity token issued. | |
* | |
* @return true if token is valid, false if invalid. | |
*/ | |
static boolean validateAuthenticityToken(String authenticityToken) { | |
Logger.trace("VALIDATE in:%s out:%s", Scope.Session.current() | |
.getAuthenticityToken(), authenticityToken); | |
return !(authenticityToken == null || !authenticityToken | |
.equals(Scope.Session.current().getAuthenticityToken())); | |
} | |
/** | |
* Checks specific authenticity token issued and returns a forbidden page if | |
* token is invalid. otherwise does nothing. | |
* | |
* @return HTTP 403 Forbidden if token is invalid | |
*/ | |
static void checkAuthenticityToken(String authenticityToken) { | |
if (!validateAuthenticityToken(authenticityToken)) { | |
forbidden("Bad authenticity token. Please try again."); | |
} | |
} | |
/** | |
* @return User id of connected user, or null. | |
*/ | |
static String connected() { | |
return session.get(USER_ID_SESSION_KEY); | |
} | |
static boolean isConnected() { | |
return connected() != null; | |
} | |
/** | |
* @return {@link User} instance of signed in user | |
*/ | |
static User connectedUser() { | |
return UserService.getUser(connected()); | |
} | |
/** | |
* Logs in to the account if "remember me" cookie exist on the client and | |
* request. | |
* | |
* @return true if remember me cookie is used and was valid. | |
*/ | |
private static boolean useRememberMe(Request request) { | |
Http.Cookie remember = request.cookies.get(REMEMBER_ME_COOKIE_KEY); | |
// remember.value should be in format of: user_id:some_signed_hash | |
if (remember != null && remember.value.indexOf(':') > 0) { | |
String uid = remember.value.substring(0, | |
remember.value.indexOf(':')); | |
String sign = remember.value | |
.substring(remember.value.indexOf(':') + 1); | |
Logger.debug("Encountered remember me: %s", remember.value); | |
Logger.debug("Remember uid: %s", uid); | |
User u = null; | |
if (uid != null) | |
u = UserService.getUser(uid); | |
if (u != null && rememberMeHash(u).equals(sign)) { | |
// remember cookie valid, make the user signed in | |
grantAccess(u); | |
Logger.debug("Remember-me access granted to user %s", uid); | |
return true; // remember-me is used. | |
} | |
} | |
return false; // remember-me didn't work. | |
} | |
/** | |
* Adjusts relevant session and cookie keys for a client with given user. | |
*/ | |
static void grantAccess(User user) { | |
if (user == null) | |
throw new IllegalArgumentException(); | |
session.put("email", user.getEmail()); | |
session.put(USER_ID_SESSION_KEY, user.getId()); | |
} | |
/** | |
* Removes session and remember-me cookies from the client | |
*/ | |
static void logOut(Response response) { | |
session.clear(); | |
response.removeCookie(REMEMBER_ME_COOKIE_KEY); | |
Logger.debug("User logged out."); | |
} | |
/** | |
* Sets response cookie for client to remember given user forever. | |
*/ | |
static void setRememberMe(Response response, User user) { | |
response.setCookie(REMEMBER_ME_COOKIE_KEY, user.getId() + ":" | |
+ rememberMeHash(user), "999d"); // forever alone | |
} | |
/** | |
* Signs string "user_id:user_password" with application id in order to save | |
* it in remember-me cookie field. | |
*/ | |
private static String rememberMeHash(User u) { | |
return Crypto.sign(u.getId() + ":" + u.getPassword()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment