import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; import sun.misc.BASE64Decoder; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * Extracts the customer id from a Ruby session using a cookie recived in the * HttpServletRequest. The environment needs to provide a SimpleJdbcTemplate * instance to give access to the database holding the actual session data. * */ public class RailsSessionIntegrationHelper { private SimpleJdbcTemplate simpleJdbcTemplate; private static final String RAILS_SESSION_PROP_NAME = "customer"; public RailsSessionIntegrationHelper(SimpleJdbcTemplate simpleJdbcTemplate) { this.simpleJdbcTemplate = simpleJdbcTemplate; } public int getCustomerId(HttpServletRequest req) { Integer customerId = (Integer)req.getSession().getAttribute("customerId"); if (customerId != null) { return customerId; } String cookieKey = null; Cookie[] cs = req.getCookies(); if (cs == null) { return 0; } for (Cookie c : cs) { if ("_session_id".equals(c.getName())) { cookieKey = c.getValue(); } } if (cookieKey == null) { return 0; } String data = getSessionData(cookieKey); if (data == null) { return 0; } customerId = extractCustomerId(data); if (customerId > 0) { req.getSession().setAttribute("customerId", customerId); } return customerId; } static int extractCustomerId(String data) { byte[] bs; try { bs = new BASE64Decoder().decodeBuffer(data); byte[] needle = RAILS_SESSION_PROP_NAME.getBytes("US-ASCII"); int i = at(needle, bs); if (i == -1) { return 0; } i += needle.length; return parseIntInQuotes(bs, i); } catch (IOException e) { throw new Error(e); } } static int parseIntInQuotes(byte[] data, int offset) { StringBuilder sb = new StringBuilder(); int start = byteAt(data, (byte)'"', offset); if (start == -1) { return -1; } for (int i = start + 1; i < data.length; i++) { byte b = data[i]; if (b >= '0' && b <= '9') { sb.append((char)b); } else if (b == '"') { return Integer.parseInt(sb.toString()); } } return 0; } static int at(byte[] needle, byte[] haystack) { int needleOffset = 0; for (int i = 0; i < haystack.length; i++) { if (haystack[i] == needle[needleOffset]) { needleOffset++; if (needleOffset >= needle.length ) { return i - needle.length + 1; } } else { if (needleOffset > 0) { i = i - needleOffset; } needleOffset = 0; } } if (needleOffset == needle.length) { return haystack.length - needle.length + 1; } return -1; } static int byteAt(byte[] data, byte toLookFor, int startAt) { for (int i = startAt; i < data.length; i++) { if (data[i] == toLookFor) { return i; } } return -1; } private String getSessionData(String key) { try { return simpleJdbcTemplate.queryForObject( "select data from sessions where sessid = ?", String.class, key); } catch (EmptyResultDataAccessException e) { return null; } } }