From 3735b60d10738e6d59b31fa446af7efe282376a2 Mon Sep 17 00:00:00 2001 From: Mike McKay <mfmckay@wustl.edu> Date: Tue, 24 May 2016 17:10:00 -0500 Subject: [PATCH] Added preference for how often to check if locked out users should be let back in. Made how to specify time intervals consistent within the User Logins and Session Controls section by having Failed Logins Lockout Duration and User Inactivity Lockout both be entered in Intervals. --- .../xnat/configuration/SchedulerConfig.java | 9 ++--- .../SiteConfigPreferenceHandler.java | 26 +++++++++++++- .../security/XnatSessionEventPublisher.java | 8 ++++- .../xnat/spawner/site-admin-elements.yaml | 35 ++++++++++++++----- 4 files changed, 63 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java b/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java index bab832ad..2fc83765 100644 --- a/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java @@ -52,10 +52,10 @@ public class SchedulerConfig implements SchedulingConfigurer { // } // } - @Bean - public TriggerTask resetFailedLogins() throws SiteConfigurationException { - return new TriggerTask(new ResetFailedLogins(_template, _preferences.getMaxFailedLoginsLockoutDuration()), new PeriodicTrigger(900000)); - } +// @Bean +// public TriggerTask resetFailedLogins() throws SiteConfigurationException { +// return new TriggerTask(new ResetFailedLogins(_template, _preferences.getMaxFailedLoginsLockoutDuration()), new PeriodicTrigger(900000)); +// } @Bean public TriggerTask resetEmailRequests() { @@ -106,6 +106,7 @@ public class SchedulerConfig implements SchedulingConfigurer { // taskRegistrar.addTriggerTask(rebuildSessionXmls()); XDAT.getContextService().getBean(NrgEventService.class).triggerEvent(new SiteConfigPreferenceEvent("aliasTokenTimeout", String.valueOf(XDAT.getSiteConfigPreferences().getAliasTokenTimeout()))); XDAT.getContextService().getBean(NrgEventService.class).triggerEvent(new SiteConfigPreferenceEvent("inactivityBeforeLockout", String.valueOf(XDAT.getSiteConfigPreferences().getInactivityBeforeLockout()))); + XDAT.getContextService().getBean(NrgEventService.class).triggerEvent(new SiteConfigPreferenceEvent("maxFailedLoginsLockoutDuration", String.valueOf(XDAT.getSiteConfigPreferences().getMaxFailedLoginsLockoutDuration()))); for (final TriggerTask triggerTask : _triggerTasks) { taskRegistrar.addTriggerTask(triggerTask); } diff --git a/src/main/java/org/nrg/xnat/event/listeners/SiteConfigPreferenceHandler.java b/src/main/java/org/nrg/xnat/event/listeners/SiteConfigPreferenceHandler.java index 82b939c3..9bfb3768 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/SiteConfigPreferenceHandler.java +++ b/src/main/java/org/nrg/xnat/event/listeners/SiteConfigPreferenceHandler.java @@ -8,6 +8,7 @@ import org.nrg.xdat.XDAT; import org.nrg.xdat.preferences.SiteConfigPreferenceEvent; import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.security.DisableInactiveUsers; +import org.nrg.xnat.security.ResetFailedLogins; import org.nrg.xnat.security.alias.ClearExpiredAliasTokens; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @@ -56,6 +57,12 @@ public class SiteConfigPreferenceHandler implements Consumer<Event<SiteConfigPre else if (StringUtils.equals(field.getFieldName(), "inactivityBeforeLockoutSchedule")) { updateInactivityBeforeLockout(e); } + else if (StringUtils.equals(field.getFieldName(), "maxFailedLoginsLockoutDuration")) { + updateResetFailedLogins(e); + } + else if (StringUtils.equals(field.getFieldName(), "resetFailedLoginsSchedule")) { + updateResetFailedLogins(e); + } } } } @@ -85,7 +92,23 @@ public class SiteConfigPreferenceHandler implements Consumer<Event<SiteConfigPre temp.cancel(false); } - scheduledInactivityBeforeLockout.add(XDAT.getContextService().getBeansOfType(ThreadPoolTaskScheduler.class).get("taskScheduler").schedule(new DisableInactiveUsers(XDAT.getSiteConfigPreferences().getInactivityBeforeLockout(),(int) SiteConfigPreferences.convertPGIntervalToSeconds(XDAT.getSiteConfigPreferences().getMaxFailedLoginsLockoutDuration())),new CronTrigger(XDAT.getSiteConfigPreferences().getInactivityBeforeLockoutSchedule()))); + scheduledInactivityBeforeLockout.add(XDAT.getContextService().getBeansOfType(ThreadPoolTaskScheduler.class).get("taskScheduler").schedule(new DisableInactiveUsers((new Long(SiteConfigPreferences.convertPGIntervalToSeconds(XDAT.getSiteConfigPreferences().getInactivityBeforeLockout()))).intValue(),(new Long(SiteConfigPreferences.convertPGIntervalToSeconds(XDAT.getSiteConfigPreferences().getMaxFailedLoginsLockoutDuration()))).intValue()),new CronTrigger(XDAT.getSiteConfigPreferences().getInactivityBeforeLockoutSchedule()))); + + } catch (Exception e1) { + _log.error("", e1); + } + } + + private void updateResetFailedLogins(SiteConfigPreferenceEvent e){ + try { + XDAT.getContextService().getBeansOfType(ThreadPoolTaskScheduler.class).get("taskScheduler").getScheduledThreadPoolExecutor().setRemoveOnCancelPolicy(true); + Iterator<Runnable> iter = XDAT.getContextService().getBeansOfType(ThreadPoolTaskScheduler.class).get("taskScheduler").getScheduledThreadPoolExecutor().getQueue().iterator(); + + for(ScheduledFuture temp: scheduledResetFailedLogins){ + temp.cancel(false); + } + + scheduledResetFailedLogins.add(XDAT.getContextService().getBeansOfType(ThreadPoolTaskScheduler.class).get("taskScheduler").schedule(new ResetFailedLogins(_template,XDAT.getSiteConfigPreferences().getMaxFailedLoginsLockoutDuration()),new CronTrigger(XDAT.getSiteConfigPreferences().getResetFailedLoginsSchedule()))); } catch (Exception e1) { _log.error("", e1); @@ -100,4 +123,5 @@ public class SiteConfigPreferenceHandler implements Consumer<Event<SiteConfigPre private ArrayList<ScheduledFuture> scheduledAliasTokenTimeouts = new ArrayList<ScheduledFuture>(); private ArrayList<ScheduledFuture> scheduledInactivityBeforeLockout = new ArrayList<ScheduledFuture>(); + private ArrayList<ScheduledFuture> scheduledResetFailedLogins = new ArrayList<ScheduledFuture>(); } diff --git a/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java b/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java index 437c17d7..5fec5247 100644 --- a/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java +++ b/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java @@ -11,6 +11,7 @@ package org.nrg.xnat.security; import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xft.security.UserI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +32,7 @@ import javax.servlet.ServletContextListener; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; +import java.sql.SQLException; import java.sql.Timestamp; import java.util.Calendar; import java.util.Date; @@ -53,7 +55,11 @@ public class XnatSessionEventPublisher implements HttpSessionListener, ServletCo } session.setAttribute("XNAT_CSRF", UUID.randomUUID().toString()); - session.setMaxInactiveInterval(XDAT.getSiteConfigPreferences().getSessionTimeout()*60);//Preference is in minutes and setMaxInactiveInterval wants seconds. + try { + session.setMaxInactiveInterval((new Long(SiteConfigPreferences.convertPGIntervalToSeconds(XDAT.getSiteConfigPreferences().getSessionTimeout()))).intValue());//Preference is in PG Interval and setMaxInactiveInterval wants seconds. + } catch (SQLException e1) { + _log.error("" + e); + } getContext(session.getServletContext()).publishEvent(e); } diff --git a/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml index f76a2c02..35d6213d 100644 --- a/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml +++ b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml @@ -219,24 +219,28 @@ userLoginsSessionControls: contentType: json contents: sessionTimeout: - kind: panel.input.number + kind: panel.input.text id: sessionTimeout name: sessionTimeout label: Session Timeout - description: "Interval for timing out alias tokens" + description: > + Interval for timing out user sessions. Uses + <a target="_blank" href="http://www.postgresql.org/docs/9.0/static/functions-datetime.html">PostgreSQL interval notation</a> aliasTokenTimeout: kind: panel.input.text id: aliasTokenTimeout name: aliasTokenTimeout label: Alias Token Timeout - description: Interval for timing out alias tokens. Uses + description: > + Interval for timing out alias tokens. Uses <a target="_blank" href="http://www.postgresql.org/docs/9.0/static/functions-datetime.html">PostgreSQL interval notation</a> aliasTokenTimeoutSchedule: kind: panel.input.text id: aliasTokenTimeoutSchedule name: aliasTokenTimeoutSchedule label: Alias Token Timeout Schedule - description: How often to check alias tokens for timeout (0 0 * * * * means it runs every hour). Uses + description: > + How often to check alias tokens for timeout (0 0 * * * * means it runs every hour). Uses <a target="_blank" href="http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html">Cron notation</a> sessionTimeoutMessage: kind: panel.textarea @@ -269,23 +273,36 @@ userLoginsSessionControls: label: Maximum Failed Logins description: Number of failed login attempts before accounts are temporarily locked. (-1 disables feature) failedLoginLockoutDuration: - kind: panel.input.number + kind: panel.input.text id: failedLoginLockoutDuration name: maxFailedLoginsLockoutDuration label: Failed Logins Lockout Duration - description: Number of milliseconds to lock user accounts that have exceeded the max_failed_logins count. Select (3600000 for 1 hour, 86400000 for 24 hours) + description: > + Interval of time to lock user accounts that have exceeded the max_failed_logins count. Uses + <a target="_blank" href="http://www.postgresql.org/docs/9.0/static/functions-datetime.html">PostgreSQL interval notation</a> + resetFailedLoginsSchedule: + kind: panel.input.text + id: resetFailedLoginsSchedule + name: resetFailedLoginsSchedule + label: Reset Failed Logins Schedule + description: > + How often to check if the Failed Logins Lockout Duration time has expired so locked out users can be allowed to log in again (0 0 * * * * means it runs every hour). Uses + <a target="_blank" href="http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html">Cron notation</a> userInactivityLockout: - kind: panel.input.number + kind: panel.input.text id: userInactivityLockout name: inactivityBeforeLockout label: User Inactivity Lockout - description: Number of seconds of inactivity before an account is disabled (31556926 for 1 year) + description: > + Interval of inactivity before a user account is disabled. Uses + <a target="_blank" href="http://www.postgresql.org/docs/9.0/static/functions-datetime.html">PostgreSQL interval notation</a> inactivityBeforeLockoutSchedule: kind: panel.input.text id: inactivityBeforeLockoutSchedule name: inactivityBeforeLockoutSchedule label: Inactivity Lockout Schedule - description: How often to check user accounts for inactivity (0 0 1 * * * means it runs at 1AM every day). Uses + description: > + How often to check user accounts for inactivity (0 0 1 * * * means it runs at 1AM every day). Uses <a target="_blank" href="http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html">Cron notation</a> -- GitLab