package pl.net.bluesoft.rnd.processtool.plugins; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.kernel.util.KeyValuePair; import com.liferay.portal.model.Role; import com.liferay.portal.model.User; import com.liferay.portal.service.UserLocalServiceUtil; /** * Abstract servlet with integration with Liferay. It uses liferay authentication * and session sharing * * @author mpawlak@bluesoft.net.pl * */ public abstract class AbstractLiferayServlet extends HttpServlet { private static final long serialVersionUID = -3306153687062512299L; private static Logger logger = Logger.getLogger(AbstractLiferayServlet.class.getName()); public enum Format { JSON, XML } /** Collection of authorized roles. If no role is specified, any user * can access this servlet */ public abstract Set<String> getAuthorizedRoles(); /** Name of attribute which stores authorization attribute. It should be unique through * servlets */ public abstract String getSessionAuthorizationName(); /** Is user authorization required? Should return true if it so, false otherwise */ public abstract boolean isAuthorizationRequired(); /** * Authorize user by request. There must be active liferay session for logged user to do this, and * user must have all roles, specifed by {@link getAuthorizedRoles()} */ protected boolean authorizeUserByRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { PrintWriter out = resp.getWriter(); HttpSession session = req.getSession(); /* Check if session is already authorized. If not, proceed with authorization */ if (session.getAttribute(getSessionAuthorizationName()) == null) { User liferayUser = getLiferayUser(req); /* No liferay user bound with current session, fail */ if(liferayUser == null) { out.write("No Liferay user is bound to current sesssion, abort"); return false; } /* There is user bound with current session, but it has not got all required roles */ if(!hasHelpChangeRole(liferayUser)) { out.write("User "+liferayUser.getScreenName()+" does not have all roles: "+getAuthorizedRoles()); return false; } session.setAttribute(getSessionAuthorizationName(), liferayUser.getScreenName()); } out.close(); return true; } /** Get Liferay user by given servlet request */ protected User getLiferayUser(HttpServletRequest req) throws ServletException { User userByScreenName = null; /* Try to authorized user by given servlet request. * We have to use cookies, otherwise authentication * won't work on WebSphere */ String userId = null; String password = null; String companyId = null; for (Cookie c : req.getCookies()) { if ("COMPANY_ID".equals(c.getName())) { companyId = c.getValue(); } else if ("ID".equals(c.getName())) { userId = hexStringToStringByAscii(c.getValue()); } else if ("PASSWORD".equals(c.getName())) { password = hexStringToStringByAscii(c.getValue()); } } if (userId != null && password != null && companyId != null) { try { KeyValuePair kvp = UserLocalServiceUtil.decryptUserId(Long.parseLong(companyId), userId, password); userByScreenName = UserLocalServiceUtil.getUserById(Long.valueOf(kvp.getKey())); } catch (NumberFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (PortalException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SystemException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(userByScreenName == null) { logger.warning("Failed to authorize user"); return null; } logger.info("Successfully authorized user: " + userByScreenName.getScreenName()); return userByScreenName; } public String hexStringToStringByAscii(String hexString) { byte[] bytes = new byte[hexString.length()/2]; for (int i = 0; i < hexString.length() / 2; i++) { String oneHexa = hexString.substring(i * 2, i * 2 + 2); bytes[i] = Byte.parseByte(oneHexa, 16); } try { return new String(bytes, "ASCII"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } /** Checks if there user has all roles specified by {@link getAuthorizedRoles()} */ protected boolean hasHelpChangeRole(User liferayUser) throws ServletException { try { List<Role> roles = liferayUser.getRoles(); Collection<String> userRolesNames = new ArrayList<String>(); for (Role role : roles) userRolesNames.add(role.getName()); return userRolesNames.containsAll(getAuthorizedRoles()); } catch (SystemException e) { logger.log(Level.SEVERE, e.getMessage(), e); throw new ServletException(e); } } /** Get request parameter from given request */ protected String getRequestParamter(HttpServletRequest req, String parameterKey) { String parameterValue = req.getParameter(parameterKey); if (parameterValue == null) throw new IllegalArgumentException("No "+parameterKey+" specified. Please run servlet with '"+parameterKey+"' parameter"); return parameterValue; } @Override public void init() throws ServletException { super.init(); logger.info(this.getClass().getSimpleName() + " INITIALIZED: " + getServletContext().getContextPath()); } @Override public void destroy() { super.destroy(); logger.info(this.getClass().getSimpleName() + " DESTROYED"); } }