Cache OpenID discovery results inside of Ehcache

We only hold results for 5 minutes by default, giving us enough
time to complete a login request without redoing the discovery,
and maybe for a few other logins, but we still expire out the
cache entries within a reasonable time window in case the server
information changes.

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-05-06 09:02:25 -07:00
parent 7cd9c012a5
commit 0e59151830
3 changed files with 61 additions and 8 deletions

View File

@@ -31,6 +31,7 @@ import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.reviewdb.SchemaVersion;
import com.google.gerrit.client.reviewdb.SystemConfig;
import com.google.gerrit.client.reviewdb.TrustedExternalId;
import com.google.gerrit.client.reviewdb.SystemConfig.LoginType;
import com.google.gerrit.client.rpc.Common;
import com.google.gerrit.client.workflow.NoOpFunction;
import com.google.gerrit.client.workflow.SubmitFunction;
@@ -233,6 +234,14 @@ public class GerritServer {
final Configuration mgrCfg = new Configuration();
configureDiskStore(mgrCfg);
configureDefaultCache(mgrCfg);
if (sConfig.getLoginType() == LoginType.OPENID) {
final CacheConfiguration c;
c = configureNamedCache(mgrCfg, "openid", false, 5);
c.setTimeToLiveSeconds(c.getTimeToIdleSeconds());
mgrCfg.addCache(c);
}
return mgrCfg;
}

View File

@@ -33,6 +33,10 @@ import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.ResultSet;
import com.google.gwtorm.client.Transaction;
import net.sf.ehcache.Element;
import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
import org.openid4java.consumer.ConsumerException;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.consumer.VerificationResult;
@@ -84,6 +88,10 @@ class OpenIdServiceImpl implements OpenIdService {
private static OpenIdServiceImpl INSTANCE;
private static boolean useOpenID() {
return Common.getGerritConfig().getLoginType() == SystemConfig.LoginType.OPENID;
}
static synchronized OpenIdServiceImpl getInstance() throws ConsumerException,
OrmException, XsrfException {
if (INSTANCE == null) {
@@ -94,17 +102,34 @@ class OpenIdServiceImpl implements OpenIdService {
private final GerritServer server;
private final ConsumerManager manager;
private final SelfPopulatingCache discoveryCache;
private OpenIdServiceImpl() throws ConsumerException, OrmException,
XsrfException {
server = GerritServer.getInstance();
manager = new ConsumerManager();
if (useOpenID()) {
discoveryCache =
new SelfPopulatingCache(server.getCache("openid"),
new CacheEntryFactory() {
public Object createEntry(final Object objKey) throws Exception {
try {
final List<?> list = manager.discover((String) objKey);
return list != null && !list.isEmpty() ? list : null;
} catch (DiscoveryException e) {
return null;
}
}
});
} else {
discoveryCache = null;
}
}
public void discover(final String openidIdentifier,
final SignInDialog.Mode mode, final boolean remember,
final String returnToken, final AsyncCallback<DiscoveryResult> callback) {
if (Common.getGerritConfig().getLoginType() != SystemConfig.LoginType.OPENID) {
if (!useOpenID()) {
callback.onFailure(new IllegalStateException("OpenID not enabled"));
return;
}
@@ -514,18 +539,18 @@ class OpenIdServiceImpl implements OpenIdService {
private State init(final HttpServletRequest httpReq,
final String openidIdentifier, final SignInDialog.Mode mode,
final boolean remember, final String returnToken) {
List<?> servers;
try {
servers = manager.discover(openidIdentifier);
} catch (DiscoveryException de) {
servers = null;
final Element serverCache = discoveryCache.get(openidIdentifier);
if (serverCache == null) {
return null;
}
if (servers == null || servers.isEmpty()) {
final List<?> list = (List<?>) serverCache.getObjectValue();
if (list == null || list.isEmpty()) {
return null;
}
final String contextUrl = GerritServer.serverUrl(httpReq);
final DiscoveryInformation discovered = manager.associate(servers);
final DiscoveryInformation discovered = manager.associate(list);
final UrlEncoded retTo = new UrlEncoded(contextUrl + "login");
retTo.put(P_MODE, mode.name());
if (returnToken != null && returnToken.length() > 0) {

View File

@@ -15,8 +15,11 @@
package com.google.gerrit.server.ssh;
import com.google.gerrit.client.data.GroupCache;
import com.google.gerrit.client.reviewdb.SystemConfig.LoginType;
import com.google.gerrit.client.rpc.Common;
import java.io.IOException;
/** Causes the caches to purge all entries and reload. */
class AdminFlushCaches extends AbstractCommand {
@Override
@@ -27,8 +30,24 @@ class AdminFlushCaches extends AbstractCommand {
Common.getProjectCache().flush();
Common.getAccountCache().flush();
SshUtil.flush();
if (Common.getGerritConfig().getLoginType() == LoginType.OPENID) {
flushCache("openid");
}
} else {
throw new Failure(1, "fatal: Not a Gerrit administrator");
}
}
private void flushCache(final String name) {
try {
getGerritServer().getCache(name).removeAll();
} catch (Throwable e1) {
try {
err.write(("warning: cannot flush cache " + name + ": " + err
.toString()).getBytes("UTF-8"));
} catch (IOException e2) {
}
}
}
}