package com.plexobject.rbac.web.utils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.NewCookie;
import org.apache.commons.validator.GenericValidator;
import org.apache.log4j.Logger;
import com.plexobject.rbac.Configuration;
import com.plexobject.rbac.domain.Domain;
import com.plexobject.rbac.domain.Tuple;
import com.plexobject.rbac.utils.PasswordUtils;
public class WebUtils {
private static final Logger LOGGER = Logger.getLogger(WebUtils.class);
private static final String SESSION = "session";
private static final int SESSION_EXPIRATION_IN_MINUTES = Configuration
.getInstance().getInteger("session_expiration_in_minutes", 60 * 24); // 24-HOURS
private static final boolean SECURED_SESSION = Configuration.getInstance()
.getBoolean("secured_session_cookie");
private static final String SESSION_COOKIE_DOMAIN = Configuration
.getInstance().getProperty("session_cookie_domain");
public static NewCookie createSessionCookie(final String domain,
final String subjectName) throws NoSuchAlgorithmException,
NoSuchProviderException, NoSuchPaddingException,
InvalidKeyException, ShortBufferException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException, UnsupportedEncodingException {
if (GenericValidator.isBlankOrNull(domain)) {
throw new IllegalArgumentException("domain not specified");
}
if (GenericValidator.isBlankOrNull(subjectName)) {
throw new IllegalArgumentException("subjectName not specified");
}
long expiresAt = System.currentTimeMillis()
+ (SESSION_EXPIRATION_IN_MINUTES * 60L * 1000L);
String session = createSession(domain, subjectName, expiresAt);
return new NewCookie(SESSION, session, "/", SESSION_COOKIE_DOMAIN,
domain + ":" + subjectName, SESSION_EXPIRATION_IN_MINUTES * 60,
SECURED_SESSION);
}
public static String getDomain(HttpServletRequest req) {
String uri = req.getRequestURI();
String[] t = uri.split("/");
if (uri.startsWith("/api/security/") && t.length > 4) { // /api/security/login/domain
return t[4];
}
Tuple domainAndSubject = verifySession(req);
if (domainAndSubject != null) {
return domainAndSubject.first();
}
return Domain.DEFAULT_DOMAIN_NAME;
}
public static Tuple verifySession(HttpServletRequest req) {
try {
String b64Session = getCookieValue(req, SESSION);
return verifySession(b64Session);
} catch (Exception e) {
LOGGER.error("failed to verify session", e);
return null;
}
}
public static String getCookieValue(HttpServletRequest req, String name) {
Cookie[] cookies = req.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(name)) {
return cookie.getValue();
}
}
}
return null;
}
private static String createSession(final String domain,
final String subjectName, long expiresAt)
throws NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException, InvalidKeyException, ShortBufferException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException, UnsupportedEncodingException {
String payload = domain + ":" + subjectName + ":" + expiresAt;
String ecnrypted = PasswordUtils.encrypt(payload);
return PasswordUtils.byteToBase64(ecnrypted.getBytes());
}
private static Tuple verifySession(String b64Session) throws IOException,
NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException, InvalidKeyException, ShortBufferException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException, InvalidKeySpecException {
if (!GenericValidator.isBlankOrNull(b64Session)) {
final String encryptedSession = new String(PasswordUtils
.base64ToByte(b64Session));
final String session = PasswordUtils.decrypt(encryptedSession);
String[] t = session.split(":");
if (t.length == 3) {
long expiresAt = Long.valueOf(t[2]);
if (expiresAt >= System.currentTimeMillis()) {
return new Tuple(t[0], t[1]);
}
}
}
return null;
}
}