Skip to content

Instantly share code, notes, and snippets.

@ahmetb
Created February 21, 2012 21:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ahmetb/1878904 to your computer and use it in GitHub Desktop.
Save ahmetb/1878904 to your computer and use it in GitHub Desktop.
play secure module alternative
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