Java tutorial
/******************************************************************************* * Copyright (c) 2015 The Board of Trustees of the Leland Stanford Junior University * BY CLICKING ON "ACCEPT," DOWNLOADING, OR OTHERWISE USING EPAD, YOU AGREE TO THE FOLLOWING TERMS AND CONDITIONS: * STANFORD ACADEMIC SOFTWARE SOURCE CODE LICENSE FOR * "ePAD Annotation Platform for Radiology Images" * * This Agreement covers contributions to and downloads from the ePAD project ("ePAD") maintained by The Board of Trustees * of the Leland Stanford Junior University ("Stanford"). * * * Part A applies to downloads of ePAD source code and/or data from ePAD. * * * Part B applies to contributions of software and/or data to ePAD (including making revisions of or additions to code * and/or data already in ePAD), which may include source or object code. * * Your download, copying, modifying, displaying, distributing or use of any ePAD software and/or data from ePAD * (collectively, the "Software") is subject to Part A. Your contribution of software and/or data to ePAD (including any * that occurred prior to the first publication of this Agreement) is a "Contribution" subject to Part B. Both Parts A and * B shall be governed by and construed in accordance with the laws of the State of California without regard to principles * of conflicts of law. Any legal action involving this Agreement or the Research Program will be adjudicated in the State * of California. This Agreement shall supersede and replace any license terms that you may have agreed to previously with * respect to ePAD. * * PART A. DOWNLOADING AGREEMENT - LICENSE FROM STANFORD WITH RIGHT TO SUBLICENSE ("SOFTWARE LICENSE"). * 1. As used in this Software License, "you" means the individual downloading and/or using, reproducing, modifying, * displaying and/or distributing Software and the institution or entity which employs or is otherwise affiliated with you. * Stanford hereby grants you, with right to sublicense, with respect to Stanford's rights in the Software, a * royalty-free, non-exclusive license to use, reproduce, make derivative works of, display and distribute the Software, * provided that: (a) you adhere to all of the terms and conditions of this Software License; (b) in connection with any * copy, distribution of, or sublicense of all or any portion of the Software, the terms and conditions in this Software * License shall appear in and shall apply to such copy and such sublicense, including without limitation all source and * executable forms and on any user documentation, prefaced with the following words: "All or portions of this licensed * product have been obtained under license from The Board of Trustees of the Leland Stanford Junior University. and are * subject to the following terms and conditions" AND any user interface to the Software or the "About" information display * in the Software will display the following: "Powered by ePAD http://epad.stanford.edu;" (c) you preserve and maintain * all applicable attributions, copyright notices and licenses included in or applicable to the Software; (d) modified * versions of the Software must be clearly identified and marked as such, and must not be misrepresented as being the * original Software; and (e) you consider making, but are under no obligation to make, the source code of any of your * modifications to the Software freely available to others on an open source basis. * * 2. The license granted in this Software License includes without limitation the right to (i) incorporate the Software * into your proprietary programs (subject to any restrictions applicable to such programs), (ii) add your own copyright * statement to your modifications of the Software, and (iii) provide additional or different license terms and conditions * in your sublicenses of modifications of the Software; provided that in each case your use, reproduction or distribution * of such modifications otherwise complies with the conditions stated in this Software License. * 3. This Software License does not grant any rights with respect to third party software, except those rights that * Stanford has been authorized by a third party to grant to you, and accordingly you are solely responsible for (i) * obtaining any permissions from third parties that you need to use, reproduce, make derivative works of, display and * distribute the Software, and (ii) informing your sublicensees, including without limitation your end-users, of their * obligations to secure any such required permissions. * 4. You agree that you will use the Software in compliance with all applicable laws, policies and regulations including, * but not limited to, those applicable to Personal Health Information ("PHI") and subject to the Institutional Review * Board requirements of the your institution, if applicable. Licensee acknowledges and agrees that the Software is not * FDA-approved, is intended only for research, and may not be used for clinical treatment purposes. Any commercialization * of the Software is at the sole risk of you and the party or parties engaged in such commercialization. You further agree * to use, reproduce, make derivative works of, display and distribute the Software in compliance with all applicable * governmental laws, regulations and orders, including without limitation those relating to export and import control. * 5. You or your institution, as applicable, will indemnify, hold harmless, and defend Stanford against any third party * claim of any kind made against Stanford arising out of or related to the exercise of any rights granted under this * Agreement, the provision of Software, or the breach of this Agreement. Stanford provides the Software AS IS and WITH ALL * FAULTS. Stanford makes no representations and extends no warranties of any kind, either express or implied. Among * other things, Stanford disclaims any express or implied warranty in the Software: * (a) of merchantability, of fitness for a particular purpose, * (b) of non-infringement or * (c) arising out of any course of dealing. * * Title and copyright to the Program and any associated documentation shall at all times remain with Stanford, and * Licensee agrees to preserve same. Stanford reserves the right to license the Program at any time for a fee. * 6. None of the names, logos or trademarks of Stanford or any of Stanford's affiliates or any of the Contributors, or any * funding agency, may be used to endorse or promote products produced in whole or in part by operation of the Software or * derived from or based on the Software without specific prior written permission from the applicable party. * 7. Any use, reproduction or distribution of the Software which is not in accordance with this Software License shall * automatically revoke all rights granted to you under this Software License and render Paragraphs 1 and 2 of this * Software License null and void. * 8. This Software License does not grant any rights in or to any intellectual property owned by Stanford or any * Contributor except those rights expressly granted hereunder. * * PART B. CONTRIBUTION AGREEMENT - LICENSE TO STANFORD WITH RIGHT TO SUBLICENSE ("CONTRIBUTION AGREEMENT"). * 1. As used in this Contribution Agreement, "you" means an individual providing a Contribution to ePAD and the * institution or entity which employs or is otherwise affiliated with you. * 2. This Contribution Agreement applies to all Contributions made to ePAD at any time. By making a Contribution you * represent that: (i) you are legally authorized and entitled by ownership or license to make such Contribution and to * grant all licenses granted in this Contribution Agreement with respect to such Contribution; (ii) if your Contribution * includes any patient data, all such data is de-identified in accordance with U.S. confidentiality and security laws and * requirements, including but not limited to the Health Insurance Portability and Accountability Act (HIPAA) and its * regulations, and your disclosure of such data for the purposes contemplated by this Agreement is properly authorized and * in compliance with all applicable laws and regulations; and (iii) you have preserved in the Contribution all applicable * attributions, copyright notices and licenses for any third party software or data included in the Contribution. * 3. Except for the licenses you grant in this Agreement, you reserve all right, title and interest in your Contribution. * 4. You hereby grant to Stanford, with the right to sublicense, a perpetual, worldwide, non-exclusive, no charge, * royalty-free, irrevocable license to use, reproduce, make derivative works of, display and distribute the Contribution. * If your Contribution is protected by patent, you hereby grant to Stanford, with the right to sublicense, a perpetual, * worldwide, non-exclusive, no-charge, royalty-free, irrevocable license under your interest in patent rights embodied in * the Contribution, to make, have made, use, sell and otherwise transfer your Contribution, alone or in combination with * ePAD or otherwise. * 5. You acknowledge and agree that Stanford ham may incorporate your Contribution into ePAD and may make your * Contribution as incorporated available to members of the public on an open source basis under terms substantially in * accordance with the Software License set forth in Part A of this Agreement. You further acknowledge and agree that * Stanford shall have no liability arising in connection with claims resulting from your breach of any of the terms of * this Agreement. * 6. YOU WARRANT THAT TO THE BEST OF YOUR KNOWLEDGE YOUR CONTRIBUTION DOES NOT CONTAIN ANY CODE OBTAINED BY YOU UNDER AN * OPEN SOURCE LICENSE THAT REQUIRES OR PRESCRIBES DISTRBUTION OF DERIVATIVE WORKS UNDER SUCH OPEN SOURCE LICENSE. (By way * of non-limiting example, you will not contribute any code obtained by you under the GNU General Public License or other * so-called "reciprocal" license.) *******************************************************************************/ package edu.stanford.epad.epadws.security; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.codec.binary.Base64; import org.mindrot.jbcrypt.BCrypt; import edu.stanford.epad.common.util.EPADConfig; import edu.stanford.epad.common.util.EPADLogger; import edu.stanford.epad.epadws.models.User; import edu.stanford.epad.epadws.service.DefaultEpadProjectOperations; import edu.stanford.epad.epadws.service.EpadProjectOperations; /** * EPAD session management methods * * @author dev (based on XNATSessionOperations) * */ public class EPADSessionOperations { private static final EPADLogger log = EPADLogger.getInstance(); private static final String LOGIN_EXCEPTION_MESSAGE = "Internal login error"; private static Map<String, EPADSession> currentSessions = new HashMap<String, EPADSession>(); private static EPADSession adminSession = null; private static final EpadProjectOperations projectOperations = DefaultEpadProjectOperations.getInstance(); private static final IdGenerator idGenerator = new IdGenerator(); private static final int SESSION_LIFESPAN = 60; // 1 hour in mins public static class EPADSessionResponse { public final int statusCode; public final String response; public final String message; public EPADSessionResponse(int responseCode, String response, String message) { this.statusCode = responseCode; this.response = response; this.message = message; } } public static String getAdminSessionID() throws Exception { if (adminSession != null && adminSession.isValid()) { return adminSession.getSessionId(); } String xnatUploadProjectUser = EPADConfig.xnatUploadProjectUser; String xnatUploadProjectPassword = EPADConfig.xnatUploadProjectPassword; log.info("Getting EPAD Admin Session"); EPADSession session = EPADSessionOperations.createNewEPADSession(xnatUploadProjectUser, xnatUploadProjectPassword); if (session != null) { adminSession = session; return session.getSessionId(); } else throw new Exception("Error getting admin session"); } public static EPADSessionResponse authenticateUser(HttpServletRequest httpRequest) { String username = extractUserNameFromAuthorizationHeader(httpRequest); String password = extractPasswordFromAuthorizationHeader(httpRequest); if (username == null || username.length() == 0) { username = httpRequest.getParameter("username"); password = httpRequest.getParameter("password"); } EPADSession session = null; try { if (username != null && password == null && httpRequest.getParameter("adminuser") != null) { session = EPADSessionOperations.createProxySession(username, httpRequest.getParameter("adminuser"), httpRequest.getParameter("adminpassword")); } else if (username == null && httpRequest.getAuthType().equals("WebAuth") && httpRequest.getRemoteUser() != null) { if (password != null && password.equals(EPADConfig.webAuthPassword)) session = EPADSessionOperations.createPreAuthenticatedSession(httpRequest.getRemoteUser()); } else { session = EPADSessionOperations.createNewEPADSession(username, password); } EPADSessionResponse response = new EPADSessionResponse(HttpServletResponse.SC_OK, session.getSessionId(), ""); log.info("Session ID " + response.response + " generated for user " + username); return response; } catch (Exception x) { EPADSessionResponse response = new EPADSessionResponse(HttpServletResponse.SC_UNAUTHORIZED, null, x.getMessage()); return response; } } public static String authenticateWebAuthUser(String username, String password) throws Exception { if (password != null && password.trim().length() > 0) { if (password.equals(EPADConfig.webAuthPassword)) { EPADSession session = EPADSessionOperations.createPreAuthenticatedSession(username); return session.getSessionId(); } } return null; } public static int invalidateSessionID(HttpServletRequest httpRequest) { String jsessionID = getJSessionIDFromRequest(httpRequest); if (jsessionID != null) { invalidateSessionID(jsessionID); return HttpServletResponse.SC_OK; } else return HttpServletResponse.SC_BAD_REQUEST; } public static void invalidateSessionID(String jsessionID) { EPADSession session = currentSessions.remove(jsessionID); if (session != null) session.setValid(false); } public static boolean hasValidSessionID(HttpServletRequest httpRequest) { String jsessionID = EPADSessionOperations.getJSessionIDFromRequest(httpRequest); if (jsessionID == null) // The getJSessionIDFromRequest method logs warning in this case. return false; else return hasValidSessionID(jsessionID, httpRequest); } public static boolean hasValidSessionID(String jsessionID) { return hasValidSessionID(jsessionID, null); } public static boolean hasValidSessionID(String jsessionID, HttpServletRequest httpRequest) { EPADSession session = currentSessions.get(jsessionID); if (session != null) { session.setLastActivity(new Date()); if (httpRequest != null) { String url = httpRequest.getRequestURL().toString(); if (url.indexOf("eventresource") == -1) session.setLastRequest(url); } session.setLifespan(EPADSessionOperations.SESSION_LIFESPAN); return true; } //log.warning("SessionId:" + jsessionID + " not found in active sessions"); return false; } public static String getJSessionIDFromRequest(HttpServletRequest servletRequest) { String jSessionID = null; Cookie[] cookies = servletRequest.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if ("JSESSIONID".equalsIgnoreCase(cookie.getName())) { jSessionID = cookie.getValue(); break; } } } if (jSessionID == null) { log.warning("No JSESSIONID cookie present in request " + servletRequest.getRequestURL()); } else { int comma = jSessionID.indexOf(","); if (comma != -1) { log.warning("Multiple cookies:" + jSessionID); jSessionID = jSessionID.substring(0, comma); } } return jSessionID; } public static String extractUserNameFromAuthorizationHeader(HttpServletRequest httpRequest) { String credentials = extractCredentialsFromAuthorizationHeader(httpRequest); String[] values = credentials.split(":", 2); if (values.length != 0 && values[0] != null) return values[0]; else return ""; } public static void checkSessionTimeout() { List<String> expiredSessions = new ArrayList<String>(); for (String sessionID : currentSessions.keySet()) { EPADSession session = currentSessions.get(sessionID); int lifespan = session.getLifespan(); lifespan--; session.setLifespan(lifespan); if (lifespan == 0) { session.setValid(false); expiredSessions.add(sessionID); } } for (String sessionID : expiredSessions) { currentSessions.remove(sessionID); } } public static void setSessionHost(String sessionID, String hostName, String hostAddr) { EPADSession session = currentSessions.get(sessionID); if (session != null) { session.setRemoteHost(hostName); session.setRemoteAddr(hostAddr); } } public static String getSessionHost(String sessionID) { EPADSession session = currentSessions.get(sessionID); if (session != null) { if (session.getRemoteHost() == null) return session.getRemoteAddr(); else if (session.getRemoteAddr() == null) return session.getRemoteHost(); else if (session.getRemoteAddr().equals(session.getRemoteHost())) return session.getRemoteHost(); else return session.getRemoteHost() + ":" + session.getRemoteAddr(); } else return null; } private static EPADSession createNewEPADSession(String username, String password) throws Exception { User user = projectOperations.getUser(username); if (user == null) throw new Exception("User " + username + " not found"); if (!user.isEnabled()) throw new Exception("User " + username + " is disabled"); String webAuthPassword = EPADConfig.webAuthPassword; if (user.getPassword().length() >= 60 && BCrypt.checkpw(password, user.getPassword())) { String sessionId = idGenerator.generateId(16); EPADSession session = new EPADSession(sessionId, username, SESSION_LIFESPAN); currentSessions.put(sessionId, session); return session; } else if (webAuthPassword != null && webAuthPassword.length() > 0 && user.getPassword().length() >= 60 && BCrypt.checkpw(password, webAuthPassword)) { String sessionId = idGenerator.generateId(16); EPADSession session = new EPADSession(sessionId, username, SESSION_LIFESPAN); currentSessions.put(sessionId, session); return session; } else { log.debug("Invalid Password:" + user.getPassword() + " Entered:" + password); if (user.getPassword().length() < 60) // clear password set by admin manually on rare occasions { if (password.equals(user.getPassword())) { if (!user.isPasswordExpired()) { user.setPasswordExpired(true); user.save(); } String sessionId = idGenerator.generateId(16); EPADSession session = new EPADSession(sessionId, username, SESSION_LIFESPAN); currentSessions.put(sessionId, session); return session; } } throw new Exception("Error creating new session, invalid password"); } } private static EPADSession createProxySession(String username, String adminuser, String adminpassword) throws Exception { User user = projectOperations.getUser(username); if (user == null) throw new Exception("User " + username + " not found"); if (!user.isEnabled()) throw new Exception("User " + username + " is disabled"); User admin = projectOperations.getUser(adminuser); if (admin == null) throw new Exception("User " + admin + " not found"); if (!admin.isEnabled()) throw new Exception("User " + admin + " is disabled"); if (user.getPassword().length() >= 60 && BCrypt.checkpw(adminpassword, admin.getPassword())) { String sessionId = idGenerator.generateId(16); EPADSession session = new EPADSession(sessionId, username, SESSION_LIFESPAN); currentSessions.put(sessionId, session); return session; } else { if (user.getPassword().length() < 60) // clear password set by admin manually on rare occasions { if (adminpassword.equals(admin.getPassword())) { if (!admin.isPasswordExpired()) { admin.setPasswordExpired(true); admin.save(); } String sessionId = idGenerator.generateId(16); EPADSession session = new EPADSession(sessionId, username, SESSION_LIFESPAN); currentSessions.put(sessionId, session); return session; } } throw new Exception("Error creating new session, invalid admin password"); } } private static EPADSession createPreAuthenticatedSession(String username) throws Exception { User user = projectOperations.getUser(username); if (user == null) throw new Exception("User " + username + " not found"); String sessionId = idGenerator.generateId(16); EPADSession session = new EPADSession(sessionId, username, SESSION_LIFESPAN); currentSessions.put(sessionId, session); return session; } private static String extractPasswordFromAuthorizationHeader(HttpServletRequest request) { String credentials = extractCredentialsFromAuthorizationHeader(request); String[] values = credentials.split(":", 2); if (values.length > 1 && values[1] != null) return values[1]; else return ""; } private static String[] extractUsernamePasswordFromAuthorizationHeader(HttpServletRequest request) { String credentials = extractCredentialsFromAuthorizationHeader(request); String[] values = credentials.split(":", 2); if (values.length > 1) return values; else return null; } private static String extractCredentialsFromAuthorizationHeader(HttpServletRequest request) { String authorizationHeader = request.getHeader("Authorization"); String credentials = ""; if (authorizationHeader != null && authorizationHeader.startsWith("Basic")) { String base64Credentials = authorizationHeader.substring("Basic".length()).trim(); credentials = new String(Base64.decodeBase64(base64Credentials), Charset.forName("UTF-8")); } return credentials; } public static Map<String, EPADSession> getCurrentSessions() { return currentSessions; } public static String getSessionUser(String sessionID) { EPADSession session = currentSessions.get(sessionID); if (session != null) return session.getUsername(); else return null; } }