UIMA-6085 DUCC Web Server (WS) login session should be coordinated amongst DUCC head nodes git-svn-id: https://svn.apache.org/repos/asf/uima/uima-ducc/trunk@1864509 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccCookies.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccCookies.java index 5f2cfd1..64cbfa4 100644 --- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccCookies.java +++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccCookies.java
@@ -71,7 +71,8 @@ private static final String filter_users_style = "filter_users_style"; private static final String role = "role"; - private static final String uid = "uid"; + private static final String key_uid = "uid"; + private static final String key_loginToken = "loginToken"; public static final String cookieStyleTable = duccCookiePrefix+table_style; public static final String cookieStyleDate = duccCookiePrefix+date_style; @@ -80,7 +81,8 @@ public static final String cookieStyleFilterUsers = duccCookiePrefix+filter_users_style; public static final String cookieRole = duccCookiePrefix+role; - public static final String cookieUid = duccCookiePrefix+uid; + public static final String cookieUid = duccCookiePrefix+key_uid; + public static final String cookieLoginToken = duccCookiePrefix+key_loginToken; public static final String valueStyleDateLong = "long"; public static final String valueStyleDateMedium = "medium"; @@ -103,6 +105,12 @@ public static final String valueRoleAdministrator = "administrator"; public static final String valueRoleUser = "user"; + public static final int seconds_per_minute = 60; + public static final int seconds_per_hour = 60*seconds_per_minute; + public static final int seconds_per_day = 24*seconds_per_hour; + public static final int seconds_per_year = 365*seconds_per_day; + public static final int seconds_per_century = 100*seconds_per_year; + protected static final String getCookieKey(String name) { return duccCookiePrefix+"name"; } @@ -137,18 +145,19 @@ return getCookie(null,request,name); } - protected static void putCookie(HttpServletResponse response, String name, String value) { + protected static void putCookie(HttpServletResponse response, String name, String value, int expiry) { String methodName = "putCookie"; Cookie cookie = new Cookie(name, value); cookie.setPath(cookieUri); + cookie.setMaxAge(expiry); response.addCookie(cookie); duccLogger.trace(methodName, null, messages.fetchLabel("name")+name+" "+messages.fetchLabel("value")+value); } - protected static void expireCookie(HttpServletResponse response, String name, String value) { - String methodName = "expireCookie"; + protected static void putCookie(HttpServletResponse response, String name, String value) { + String methodName = "putCookie"; Cookie cookie = new Cookie(name, value); - cookie.setMaxAge(0); + cookie.setPath(cookieUri); response.addCookie(cookie); duccLogger.trace(methodName, null, messages.fetchLabel("name")+name+" "+messages.fetchLabel("value")+value); } @@ -272,16 +281,58 @@ return role; } - public static String getUid(HttpServletRequest request) { - String location = "getUid"; - String uid = null; + public static String getLoginUid(HttpServletRequest request) { + String location = "getLoginUid"; + String loginUid = null; try { String cookie = getCookie(null,request,cookieUid); - uid = cookie; - duccLogger.debug(location, jobid, cookieUid+":"+uid); + loginUid = cookie; + duccLogger.debug(location, jobid, cookieUid+":"+loginUid); } catch(Exception e) { } - return uid; + return loginUid; } + + public static void setLoginUid(HttpServletResponse response, String value) { + String location = "setLoginUid"; + try { + putCookie(response, cookieUid, value); + duccLogger.debug(location, jobid, cookieUid+":"+value); + } + catch(Exception e) { + } + } + + public static String getLoginToken(HttpServletRequest request) { + String location = "getLoginToken"; + String loginToken = null; + try { + String cookie = getCookie(null,request,cookieLoginToken); + loginToken = cookie; + duccLogger.debug(location, jobid, cookieLoginToken+":"+loginToken); + } + catch(Exception e) { + } + return loginToken; + } + + public static void setLoginToken(HttpServletResponse response, String value) { + setLoginToken(response, value, seconds_per_century); + } + + public static void expireLoginToken(HttpServletResponse response) { + setLoginToken(response, "expired", 0); + } + + private static void setLoginToken(HttpServletResponse response, String value, int expiry) { + String location = "setLoginToken"; + try { + putCookie(response, cookieLoginToken, value, expiry); + duccLogger.debug(location, jobid, cookieLoginToken+":"+value); + } + catch(Exception e) { + } + } + }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java index 694b053..dbe8030 100644 --- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java +++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java
@@ -366,7 +366,7 @@ String methodName = "handleDuccServletAuthenticatorNotes"; duccLogger.trace(methodName, null, messages.fetch("enter")); StringBuffer sb = new StringBuffer(); - String uid = DuccCookies.getUid(request); + String uid = DuccCookies.getLoginUid(request); String notes = duccAuthenticator.getNotes(uid); if(notes != null) { sb.append(notes);
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerUserAuthentication.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerUserAuthentication.java index b86babd..8fcf12b 100644 --- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerUserAuthentication.java +++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerUserAuthentication.java
@@ -95,7 +95,7 @@ StringBuffer sb = new StringBuffer(); try { userId = duccWebSessionManager.getUserId(request); - boolean result = duccWebSessionManager.logout(request); + boolean result = duccWebSessionManager.logout(request, response, userId); if(result) { duccLogger.info(methodName, jobid, messages.fetch("logout ")+userId+" "+messages.fetch("success")); sb.append("success"); @@ -168,7 +168,7 @@ if(ducc_runmode_pw.length() > 0) { if(password != null) { if(password.equals(ducc_runmode_pw)) { - duccWebSessionManager.login(request, userId); + duccWebSessionManager.login(request,response,userId); sb.append("success"); } } @@ -201,7 +201,7 @@ IAuthenticationResult result2 = duccAuthenticator.isGroupMember(userId, domain, role); duccLogger.debug(methodName, jobid, messages.fetch("login ")+userId+" "+"group reason: "+result2.getReason()); if(result1.isSuccess() && result2.isSuccess()) { - duccWebSessionManager.login(request, userId); + duccWebSessionManager.login(request,response,userId); duccLogger.info(methodName, jobid, messages.fetch("login ")+userId+" "+messages.fetch("success")); sb.append("success"); }
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccWebSessionManager.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccWebSessionManager.java index df58c50..0fa6d64 100644 --- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccWebSessionManager.java +++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccWebSessionManager.java
@@ -19,13 +19,17 @@ package org.apache.uima.ducc.ws.server; import java.security.SecureRandom; -import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpServletResponse; import org.apache.uima.ducc.common.utils.DuccLogger; import org.apache.uima.ducc.common.utils.id.DuccId; +import org.apache.uima.ducc.database.login.DbUserLogin; + +/* + * Class to manage user login/logout, in coordination with browser and cookies + */ public class DuccWebSessionManager { @@ -38,20 +42,14 @@ return instance; } + private static DbUserLogin dbUserLogin = new DbUserLogin(duccLogger); + private static SecureRandom sr = new SecureRandom(); - public static final String ducc_user_id = "ducc.user.id"; - public static final String ducc_validation_id = "ducc.validation.id"; - private static final int SEGMENTS = 8; - - private class IdSet { - public String sessionId; - public String validationId; - } - - private ConcurrentHashMap<String,IdSet> map = new ConcurrentHashMap<String,IdSet>(); + // Token given to browser. When present upon subsequent calls + // user is considered logged-in. private String generateValidationId() { StringBuffer sb = new StringBuffer(); sb.append(sr.nextLong()); @@ -62,167 +60,98 @@ return sb.toString(); } - private void iRemove(String method, String userId, IdSet idSet) { - String location = "iRemove"+"."+method; - if(idSet != null) { - duccLogger.info(location, jobid, "uid:"+userId); - duccLogger.info(location, jobid, "sid:"+idSet.sessionId); - duccLogger.info(location, jobid, "vid:"+idSet.validationId); - } - } - - private void iPut(String method, String userId, IdSet idSet) { - String location = "iPut"+"."+method; - if(idSet != null) { - duccLogger.info(location, jobid, "uid:"+userId); - duccLogger.info(location, jobid, "sid:"+idSet.sessionId); - duccLogger.info(location, jobid, "vid:"+idSet.validationId); - } - } - - public void login(HttpServletRequest request, String userId) { + // login user + public void login(HttpServletRequest request, HttpServletResponse response, String userId) { String location = "login"; if(request == null) { duccLogger.debug(location, jobid, "request is null"); return; } + if(response == null) { + duccLogger.debug(location, jobid, "response is null"); + return; + } if(userId == null) { duccLogger.debug(location, jobid, "userId is null"); return; } - HttpSession session = request.getSession(); - if(session == null) { - duccLogger.debug(location, jobid, "session is null"); - return; - } - String sessionId = session.getId(); - if(sessionId == null) { - duccLogger.debug(location, jobid, "sessionId is null"); - return; - } - iRemove(location, userId, map.get(userId)); + // generate validation id String validationId = generateValidationId(); - session.setAttribute(ducc_validation_id, validationId); - session.setAttribute(ducc_user_id, userId); - IdSet idSet = new IdSet(); - idSet.validationId = validationId; - idSet.sessionId = sessionId; - map.put(userId, idSet); - iPut(location, userId, map.get(userId)); + // tell browser + DuccCookies.setLoginUid(response, userId); + DuccCookies.setLoginToken(response, validationId); + duccLogger.debug(location, jobid, userId, validationId); + // tell database + dbUserLogin.addOrReplace(userId, validationId); return; } - public boolean logout(HttpServletRequest request) { + // louout user + public boolean logout(HttpServletRequest request, HttpServletResponse response, String userId) { String location = "logout"; boolean retVal = false; if(request == null) { duccLogger.debug(location, jobid, "request is null"); return retVal; } - HttpSession session = request.getSession(); - if(session == null) { - duccLogger.debug(location, jobid, "session is null"); + if(response == null) { + duccLogger.debug(location, jobid, "response is null"); return retVal; } - String userId = (String) session.getAttribute(ducc_user_id); if(userId == null) { duccLogger.debug(location, jobid, "userId is null"); return retVal; } - String validationId = (String) session.getAttribute(ducc_validation_id); - if(validationId == null) { - duccLogger.debug(location, jobid, "validationId is null"); - return retVal; - } - String sessionId = session.getId(); - if(sessionId == null) { - duccLogger.debug(location, jobid, "sessionId is null"); - return retVal; - } - IdSet idSet = map.get(userId); - if(idSet == null) { - duccLogger.debug(location, jobid, "idSet is null"); - return retVal; - } - if(!validationId.equals(idSet.validationId)) { - duccLogger.debug(location, jobid, "given:"+validationId); - duccLogger.debug(location, jobid, "known:"+idSet.validationId); - duccLogger.debug(location, jobid, "validation mismatch!"); - return retVal; - } - if(!sessionId.equals(idSet.sessionId)) { - duccLogger.debug(location, jobid, "given:"+sessionId); - duccLogger.debug(location, jobid, "known:"+idSet.sessionId); - duccLogger.debug(location, jobid, "session mismatch!"); - return retVal; - } - session.removeAttribute(ducc_validation_id); - session.removeAttribute(ducc_user_id); - map.remove(userId); - iRemove(location, userId, idSet); - retVal = true; + retVal = isAuthentic(request); + // tell browser + DuccCookies.expireLoginToken(response); + // tell database + dbUserLogin.delete(userId); return retVal; } - public boolean isAuthentic(HttpServletRequest request) { - String location = "isAuthentic"; - if(request == null) { - duccLogger.debug(location, jobid, "request is null"); - return false; + // check token from db with token present by browser cookie + private boolean stringCompare(String s1, String s2) { + boolean retVal = false; + if(s1 != null) { + if(s2 != null) { + retVal = s1.equals(s2); + } } - HttpSession session = request.getSession(); - if(session == null) { - duccLogger.debug(location, jobid, "session is null"); - return false; - } - String userId = (String) session.getAttribute(ducc_user_id); - if(userId == null) { - duccLogger.debug(location, jobid, "userId is null"); - return false; - } - String validationId = (String) session.getAttribute(ducc_validation_id); - if(validationId == null) { - duccLogger.debug(location, jobid, "validationId is null"); - return false; - } - String sessionId = session.getId(); - if(sessionId == null) { - duccLogger.debug(location, jobid, "sessionId is null"); - return false; - } - IdSet idSet = map.get(userId); - if(idSet == null) { - duccLogger.debug(location, jobid, "idSet is null"); - return false; - } - if(!validationId.equals(idSet.validationId)) { - duccLogger.debug(location, jobid, "given:"+validationId); - duccLogger.debug(location, jobid, "known:"+idSet.validationId); - duccLogger.debug(location, jobid, "validation mismatch!"); - return false; - } - if(!sessionId.equals(idSet.sessionId)) { - duccLogger.debug(location, jobid, "given:"+sessionId); - duccLogger.debug(location, jobid, "known:"+idSet.sessionId); - duccLogger.debug(location, jobid, "session mismatch!"); - return false; - } - return true; + return retVal; } + // check if browser userid+token match same in db + public boolean isAuthentic(HttpServletRequest request) { + String location = "isAuthentic"; + boolean retVal = false; + if(request == null) { + duccLogger.debug(location, jobid, "request is null"); + return false; + } + String userId = getUserId(request); + // fetch browser + String s1 = DuccCookies.getLoginToken(request); + duccLogger.debug(location, jobid, "cookie ", retVal, userId, s1); + // fetch database + String s2 = dbUserLogin.fetch(userId); + duccLogger.debug(location, jobid, "database", retVal, userId, s2); + // compare + retVal = stringCompare(s1,s2); + return retVal; + } + + // fetch userid from browser public String getUserId(HttpServletRequest request) { - String retVal = null; String location = "getUserId"; + String retVal = null; if(request == null) { duccLogger.debug(location, jobid, "request is null"); return retVal; } - HttpSession session = request.getSession(); - if(session == null) { - duccLogger.debug(location, jobid, "session is null"); - return retVal; - } - retVal = (String) session.getAttribute(ducc_user_id); + // fetch browser + retVal = DuccCookies.getLoginUid(request); + duccLogger.debug(location, jobid, retVal); return retVal; } }