Merge pull request #395 from patriot1burke/master

fix brute shutdown
This commit is contained in:
Bill Burke 2014-05-19 10:35:49 -04:00
commit 2b525c6016
3 changed files with 171 additions and 167 deletions

258
core/src/main/java/org/keycloak/Config.java Normal file → Executable file
View file

@ -1,129 +1,129 @@
package org.keycloak;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Config {
private static ConfigProvider configProvider = new SystemPropertiesConfigProvider();
public static void init(ConfigProvider configProvider) {
Config.configProvider = configProvider;
}
public static String getAdminRealm() {
return configProvider.scope("admin").get("realm", "keycloak-admin");
}
public static String getProvider(String spi) {
return configProvider.getProvider(spi);
}
public static Scope scope(String... scope) {
return configProvider.scope(scope);
}
public static interface ConfigProvider {
String getProvider(String spi);
Scope scope(String... scope);
}
public static class SystemPropertiesConfigProvider implements ConfigProvider {
@Override
public String getProvider(String spi) {
return System.getProperties().getProperty("keycloak." + spi + ".provider");
}
@Override
public Scope scope(String... scope) {
StringBuilder sb = new StringBuilder();
sb.append("keycloak.");
for (String s : scope) {
sb.append(s);
sb.append(".");
}
return new SystemPropertiesScope(sb.toString());
}
}
public static class SystemPropertiesScope implements Scope {
private String prefix;
public SystemPropertiesScope(String prefix) {
this.prefix = prefix;
}
@Override
public String get(String key) {
return get(key, null);
}
@Override
public String get(String key, String defaultValue) {
return System.getProperty(prefix + key, defaultValue);
}
@Override
public Integer getInt(String key) {
return getInt(key, null);
}
@Override
public Integer getInt(String key, Integer defaultValue) {
String v = get(key, null);
return v != null ? Integer.parseInt(v) : defaultValue;
}
@Override
public Long getLong(String key) {
return getLong(key, null);
}
@Override
public Long getLong(String key, Long defaultValue) {
String v = get(key, null);
return v != null ? Long.parseLong(v) : defaultValue;
}
@Override
public Boolean getBoolean(String key) {
return getBoolean(key, null);
}
@Override
public Boolean getBoolean(String key, Boolean defaultValue) {
String v = get(key, null);
return v != null ? Boolean.parseBoolean(v) : defaultValue;
}
}
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public static interface Scope {
String get(String key);
String get(String key, String defaultValue);
Integer getInt(String key);
Integer getInt(String key, Integer defaultValue);
Long getLong(String key);
Long getLong(String key, Long defaultValue);
Boolean getBoolean(String key);
Boolean getBoolean(String key, Boolean defaultValue);
}
}
package org.keycloak;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Config {
private static ConfigProvider configProvider = new SystemPropertiesConfigProvider();
public static void init(ConfigProvider configProvider) {
Config.configProvider = configProvider;
}
public static String getAdminRealm() {
return configProvider.scope("admin").get("realm", "keycloak-admin");
}
public static String getProvider(String spi) {
return configProvider.getProvider(spi);
}
public static Scope scope(String... scope) {
return configProvider.scope(scope);
}
public static interface ConfigProvider {
String getProvider(String spi);
Scope scope(String... scope);
}
public static class SystemPropertiesConfigProvider implements ConfigProvider {
@Override
public String getProvider(String spi) {
return System.getProperties().getProperty("keycloak." + spi + ".provider");
}
@Override
public Scope scope(String... scope) {
StringBuilder sb = new StringBuilder();
sb.append("keycloak.");
for (String s : scope) {
sb.append(s);
sb.append(".");
}
return new SystemPropertiesScope(sb.toString());
}
}
public static class SystemPropertiesScope implements Scope {
private String prefix;
public SystemPropertiesScope(String prefix) {
this.prefix = prefix;
}
@Override
public String get(String key) {
return get(key, null);
}
@Override
public String get(String key, String defaultValue) {
return System.getProperty(prefix + key, defaultValue);
}
@Override
public Integer getInt(String key) {
return getInt(key, null);
}
@Override
public Integer getInt(String key, Integer defaultValue) {
String v = get(key, null);
return v != null ? Integer.parseInt(v) : defaultValue;
}
@Override
public Long getLong(String key) {
return getLong(key, null);
}
@Override
public Long getLong(String key, Long defaultValue) {
String v = get(key, null);
return v != null ? Long.parseLong(v) : defaultValue;
}
@Override
public Boolean getBoolean(String key) {
return getBoolean(key, null);
}
@Override
public Boolean getBoolean(String key, Boolean defaultValue) {
String v = get(key, null);
return v != null ? Boolean.parseBoolean(v) : defaultValue;
}
}
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public static interface Scope {
String get(String key);
String get(String key, String defaultValue);
Integer getInt(String key);
Integer getInt(String key, Integer defaultValue);
Long getLong(String key);
Long getLong(String key, Long defaultValue);
Boolean getBoolean(String key);
Boolean getBoolean(String key, Boolean defaultValue);
}
}

View file

@ -143,7 +143,7 @@ public class BruteForceProtector implements Runnable {
run = false;
try {
queue.offer(new ShutdownEvent());
shutdownLatch.await(5, TimeUnit.SECONDS);
shutdownLatch.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
@ -152,46 +152,50 @@ public class BruteForceProtector implements Runnable {
public void run() {
final ArrayList<LoginEvent> events = new ArrayList<LoginEvent>(TRANSACTION_SIZE + 1);
while (run) {
try {
LoginEvent take = queue.poll(2, TimeUnit.SECONDS);
if (take == null) {
continue;
}
try {
while (run) {
try {
events.add(take);
queue.drainTo(events, TRANSACTION_SIZE);
Collections.sort(events); // we sort to avoid deadlock due to ordered updates. Maybe I'm overthinking this.
ProviderSession providerSession = factory.createSession();
KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
try {
for (LoginEvent event : events) {
if (event instanceof FailedLogin) {
failure(session, event);
}
}
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
throw e;
} finally {
for (LoginEvent event : events) {
if (event instanceof FailedLogin) {
((FailedLogin) event).latch.countDown();
}
}
events.clear();
providerSession.close();
LoginEvent take = queue.poll(2, TimeUnit.SECONDS);
if (take == null) {
continue;
}
} catch (Exception e) {
logger.error("Failed processing event", e);
try {
events.add(take);
queue.drainTo(events, TRANSACTION_SIZE);
Collections.sort(events); // we sort to avoid deadlock due to ordered updates. Maybe I'm overthinking this.
ProviderSession providerSession = factory.createSession();
KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
try {
for (LoginEvent event : events) {
if (event instanceof FailedLogin) {
failure(session, event);
} else if (event instanceof ShutdownEvent) {
run = false;
}
}
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
throw e;
} finally {
for (LoginEvent event : events) {
if (event instanceof FailedLogin) {
((FailedLogin) event).latch.countDown();
}
}
events.clear();
providerSession.close();
}
} catch (Exception e) {
logger.error("Failed processing event", e);
}
} catch (InterruptedException e) {
break;
}
} catch (InterruptedException e) {
break;
} finally {
shutdownLatch.countDown();
}
} finally {
shutdownLatch.countDown();
}
}

View file

@ -133,7 +133,7 @@ public class KeycloakApplication extends Application {
}
public static void setupScheduledTasks(final ProviderSessionFactory providerSessionFactory) {
long interval = Config.scope("scheduled").getLong("interval") * 1000;
long interval = Config.scope("scheduled").getLong("interval", 60L) * 1000;
TimerProvider timer = providerSessionFactory.createSession().getProvider(TimerProvider.class);
timer.schedule(new ScheduledTaskRunner(providerSessionFactory, new ClearExpiredAuditEvents()), interval);