New version with mutex and session id used in place of session object

This commit is contained in:
Mauro Mugnaini 2021-01-19 18:16:52 +01:00
parent 13dcfe2a0e
commit e1dd978a10
2 changed files with 137 additions and 63 deletions

View File

@ -5,104 +5,139 @@ import java.util.Comparator;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import javax.servlet.http.HttpSession;
import org.gcube.oidc.rest.JWTToken; import org.gcube.oidc.rest.JWTToken;
import com.liferay.portal.model.User; import com.liferay.portal.model.User;
public class IntraVMJWTCacheProxy extends JWTCacheProxy { public class IntraVMJWTCacheProxy extends JWTCacheProxy {
private Map<User, Map<HttpSession, String>> oidcTokens; Map<User, Map<String, String>> oidcTokens;
private Map<User, Map<HttpSession, String>> rptTokens; Map<User, Map<String, String>> rptTokens;
private Comparator<User> userComparator = new Comparator<User>() {
@Override
public int compare(User u1, User u2) {
return u1.getScreenName().compareTo(u2.getScreenName());
}
};
protected IntraVMJWTCacheProxy() { protected IntraVMJWTCacheProxy() {
super();
log.info("Initializing tokens caches"); log.info("Initializing tokens caches");
oidcTokens = Collections.synchronizedMap(new TreeMap<>()); oidcTokens = Collections.synchronizedMap(new TreeMap<>(userComparator));
rptTokens = Collections.synchronizedMap(new TreeMap<>()); rptTokens = Collections.synchronizedMap(new TreeMap<>(userComparator));
} }
public void checkMap(Map<User, Map<HttpSession, String>> map, User user) { protected void checkMap(Map<User, Map<String, String>> map, User user) {
if (!map.containsKey(user)) { if (!map.containsKey(user)) {
log.debug("Initializing map for user: " + user.getScreenName()); if (log.isDebugEnabled()) {
map.put(user, Collections.synchronizedMap(new TreeMap<>(new Comparator<HttpSession>() { log.debug("Initializing map for user: " + user.getScreenName());
@Override }
public int compare(HttpSession s1, HttpSession s2) { map.put(user, Collections.synchronizedMap(new TreeMap<>()));
return s1.getId().compareTo(s2.getId());
}
})));
} }
} }
@Override @Override
public void setOIDCToken(User user, HttpSession session, JWTToken token) { public void setOIDCToken(User user, String sessionId, JWTToken token) {
checkMap(oidcTokens, user); checkMap(oidcTokens, user);
Map<HttpSession, String> oidcUserMap = oidcTokens.get(user); Map<String, String> oidcUserMap = oidcTokens.get(user);
log.trace("OIDC user's sessions recorded: " + oidcUserMap.keySet().toArray()); if (log.isTraceEnabled()) {
oidcUserMap.put(session, JWTTokenUtil.getRawContent(token)); log.trace("Setting OIDC token for user '" + user.getScreenName() + "' and session: " + sessionId);
} }
oidcUserMap.put(sessionId, JWTTokenUtil.getRawContent(token));
@Override if (log.isTraceEnabled()) {
public void setUMAToken(User user, HttpSession session, JWTToken token) { log.trace("OIDC user's sessions recorded objs: " + oidcUserMap.keySet().toArray());
checkMap(rptTokens, user);
Map<HttpSession, String> umaUserMap = rptTokens.get(user);
log.trace("UMA user's sessions recorded objs: " + umaUserMap.keySet().toArray());
umaUserMap.put(session, JWTTokenUtil.getRawContent(token));
}
@Override
public JWTToken getOIDCToken(User user, HttpSession session) {
checkMap(oidcTokens, user);
log.trace("Getting OIDC token for user '" + user.getScreenName() + "' and session obj: " + session);
return JWTTokenUtil.fromString(oidcTokens.get(user).get(session));
}
@Override
public JWTToken getUMAToken(User user, HttpSession session) {
checkMap(rptTokens, user);
log.trace("Getting UMA token for user '" + user.getScreenName() + "' and session obj: " + session);
return JWTTokenUtil.fromString(rptTokens.get(user).get(session));
}
@Override
public void removeOIDCToken(User user, HttpSession session) {
checkMap(oidcTokens, user);
if (oidcTokens.get(user).containsKey(session)) {
log.trace("Removing OIDC token for user '" + user.getScreenName() + "' and session obj: " + session);
oidcTokens.get(user).remove(session);
} }
} }
@Override @Override
public void removeUMAToken(User user, HttpSession session) { public void setUMAToken(User user, String sessionId, JWTToken token) {
checkMap(rptTokens, user); checkMap(rptTokens, user);
if (rptTokens.get(user).containsKey(session)) { Map<String, String> umaUserMap = rptTokens.get(user);
log.trace("Removing UMA token for user '" + user.getScreenName() + "' and session obj: " + session); if (log.isTraceEnabled()) {
oidcTokens.get(user).remove(session); log.trace("Setting UMA token for user '" + user.getScreenName() + "' and session: " + sessionId);
}
umaUserMap.put(sessionId, JWTTokenUtil.getRawContent(token));
if (log.isTraceEnabled()) {
log.trace("UMA user's sessions recorded objs: " + umaUserMap.keySet().toArray());
}
}
@Override
public JWTToken getOIDCToken(User user, String sessionId) {
checkMap(oidcTokens, user);
if (log.isTraceEnabled()) {
log.trace("Getting OIDC token for user '" + user.getScreenName() + "' and session: " + sessionId);
}
return JWTTokenUtil.fromString(oidcTokens.get(user).get(sessionId));
}
@Override
public JWTToken getUMAToken(User user, String sessionId) {
checkMap(rptTokens, user);
if (log.isTraceEnabled()) {
log.trace("Getting UMA token for user '" + user.getScreenName() + "' and session: " + sessionId);
}
return JWTTokenUtil.fromString(rptTokens.get(user).get(sessionId));
}
@Override
public void removeOIDCToken(User user, String sessionId) {
checkMap(oidcTokens, user);
if (oidcTokens.get(user).containsKey(sessionId)) {
if (log.isTraceEnabled()) {
log.trace("Removing OIDC token for user '" + user.getScreenName() + "' and session: " + sessionId);
}
oidcTokens.get(user).remove(sessionId);
} else {
log.info("No OIDC token is stored for user '" + user.getScreenName() + "' and session: " + sessionId);
}
}
@Override
public void removeUMAToken(User user, String sessionId) {
checkMap(rptTokens, user);
if (rptTokens.get(user).containsKey(sessionId)) {
if (log.isTraceEnabled()) {
log.trace("Removing UMA token for user '" + user.getScreenName() + "' and session: " + sessionId);
}
oidcTokens.get(user).remove(sessionId);
} else {
if (log.isTraceEnabled()) {
log.debug("No UMA token is stored for user '" + user.getScreenName() + "' and session: " + sessionId);
}
} }
} }
@Override @Override
public void removeAllOIDCTokens(User user) { public void removeAllOIDCTokens(User user) {
log.trace("Removing OIDC session's tokens of user: " + user.getScreenName()); if (log.isTraceEnabled()) {
log.trace("Removing all OIDC session's tokens of user: " + user.getScreenName());
}
oidcTokens.remove(user); oidcTokens.remove(user);
} }
@Override @Override
public void removeAllUMATokens(User user) { public void removeAllUMATokens(User user) {
log.trace("Removing UMA session's tokens of user: " + user.getScreenName()); if (log.isTraceEnabled()) {
log.trace("Removing all UMA session's tokens of user: " + user.getScreenName());
}
rptTokens.remove(user); rptTokens.remove(user);
} }
@Override @Override
public void clearOIDCTokens() { public void clearOIDCTokens() {
log.trace("Clearing OIDC tokens cache"); if (log.isTraceEnabled()) {
log.trace("Clearing OIDC tokens cache");
}
oidcTokens.clear(); oidcTokens.clear();
} }
@Override @Override
public void clearUMATokens() { public void clearUMATokens() {
log.trace("Clearing UMA tokens cache"); if (log.isTraceEnabled()) {
log.trace("Clearing UMA tokens cache");
}
rptTokens.clear(); rptTokens.clear();
} }
@ -112,4 +147,29 @@ public class IntraVMJWTCacheProxy extends JWTCacheProxy {
clearUMATokens(); clearUMATokens();
} }
@Override
public synchronized Map<String, String> getMutexFor(User user) {
checkMap(oidcTokens, user);
return oidcTokens.get(user);
}
@Override
public void dumpOnLog() {
if (log.isTraceEnabled()) {
log.trace("Cached OIDC objects: " + dumpMap(oidcTokens));
log.trace("Cached UMA objects: " + dumpMap(rptTokens));
}
}
protected String dumpMap(Map<User, Map<String, String>> map) {
StringBuffer sb = new StringBuffer();
map.forEach((u, v) -> {
sb.append(u.getScreenName() + " :");
v.forEach((s, t) -> {
sb.append(" " + s + " -> " + JWTToken.fromString(t).getTokenEssentials());
});
sb.append(", ");
});
return sb.toString();
}
} }

View File

@ -1,6 +1,8 @@
package org.gcube.portal.oidc.lr62; package org.gcube.portal.oidc.lr62;
import javax.servlet.http.HttpSession; import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import org.gcube.oidc.rest.JWTToken; import org.gcube.oidc.rest.JWTToken;
@ -16,22 +18,30 @@ public abstract class JWTCacheProxy {
public JWTCacheProxy() { public JWTCacheProxy() {
instance = this; instance = this;
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
instance.dumpOnLog();
}
}, 0, 60 * 1000);
} }
public static synchronized JWTCacheProxy getInstance() { public static synchronized JWTCacheProxy getInstance() {
return instance != null ? instance : new IntraVMJWTCacheProxy(); return instance != null ? instance : new IntraVMJWTCacheProxy();
} }
public abstract void setOIDCToken(User user, HttpSession session, JWTToken token); public abstract void setOIDCToken(User user, String sessionId, JWTToken token);
public abstract void setUMAToken(User user, HttpSession session, JWTToken token); public abstract void setUMAToken(User user, String sessionId, JWTToken token);
public abstract JWTToken getOIDCToken(User user, HttpSession session); public abstract JWTToken getOIDCToken(User user, String sessionId);
public abstract JWTToken getUMAToken(User user, HttpSession session); public abstract JWTToken getUMAToken(User user, String sessionId);
public abstract void removeOIDCToken(User user, HttpSession session); public abstract void removeOIDCToken(User user, String sessionId);
public abstract void removeUMAToken(User user, HttpSession session); public abstract void removeUMAToken(User user, String sessionId);
public abstract void removeAllOIDCTokens(User user); public abstract void removeAllOIDCTokens(User user);
@ -43,4 +53,8 @@ public abstract class JWTCacheProxy {
public abstract void clearAllTokens(); public abstract void clearAllTokens();
public abstract Map<String, String> getMutexFor(User user);
public abstract void dumpOnLog();
} }