mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-09 15:05:44 +01:00
added option to skip failed authenticators
This commit is contained in:
@@ -233,17 +233,6 @@ public class ScmConfiguration
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the realm description.
|
||||
*
|
||||
*
|
||||
* @return realm description
|
||||
*/
|
||||
public String getRealmDescription()
|
||||
{
|
||||
return realmDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date format for the user interface. This format is a
|
||||
* JavaScript date format, from the library moment.js.
|
||||
@@ -375,6 +364,17 @@ public class ScmConfiguration
|
||||
return proxyUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the realm description.
|
||||
*
|
||||
*
|
||||
* @return realm description
|
||||
*/
|
||||
public String getRealmDescription()
|
||||
{
|
||||
return realmDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the servername of the SCM-Manager host.
|
||||
*
|
||||
@@ -482,6 +482,19 @@ public class ScmConfiguration
|
||||
return forceBaseUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @since 1.36
|
||||
*/
|
||||
public boolean isSkipFailedAuthenticators()
|
||||
{
|
||||
return skipFailedAuthenticators;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -529,17 +542,6 @@ public class ScmConfiguration
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the realm description.
|
||||
*
|
||||
*
|
||||
* @param realmDescription
|
||||
*/
|
||||
public void setRealmDescription(String realmDescription)
|
||||
{
|
||||
this.realmDescription = realmDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date format for the ui.
|
||||
*
|
||||
@@ -733,6 +735,17 @@ public class ScmConfiguration
|
||||
this.proxyUser = proxyUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the realm description.
|
||||
*
|
||||
*
|
||||
* @param realmDescription
|
||||
*/
|
||||
public void setRealmDescription(String realmDescription)
|
||||
{
|
||||
this.realmDescription = realmDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -745,6 +758,19 @@ public class ScmConfiguration
|
||||
this.servername = servername;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param skipFailedAuthenticators
|
||||
*
|
||||
* @since 1.36
|
||||
*/
|
||||
public void setSkipFailedAuthenticators(boolean skipFailedAuthenticators)
|
||||
{
|
||||
this.skipFailedAuthenticators = skipFailedAuthenticators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -790,21 +816,6 @@ public class ScmConfiguration
|
||||
@XmlElement(name = "login-attempt-limit")
|
||||
private int loginAttemptLimit = -1;
|
||||
|
||||
/**
|
||||
* Login attempt timeout.
|
||||
*
|
||||
* @since 1.34
|
||||
*/
|
||||
@XmlElement(name = "login-attempt-limit-timeout")
|
||||
private long loginAttemptLimitTimeout = TimeUnit.MINUTES.toSeconds(5l);
|
||||
|
||||
/** Field description */
|
||||
private boolean enableProxy = false;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "plugin-url")
|
||||
private String pluginUrl = DEFAULT_PLUGINURL;
|
||||
|
||||
/** glob patterns for urls which are excluded from proxy */
|
||||
@XmlElement(name = "proxy-excludes")
|
||||
@XmlJavaTypeAdapter(XmlSetStringAdapter.class)
|
||||
@@ -825,10 +836,33 @@ public class ScmConfiguration
|
||||
/** @deprecated use {@link #baseUrl} */
|
||||
private String servername = "localhost";
|
||||
|
||||
/**
|
||||
* Skip failed authenticators.
|
||||
*
|
||||
* @since 1.36
|
||||
*/
|
||||
@XmlElement(name = "skip-failed-authenticators")
|
||||
private boolean skipFailedAuthenticators = false;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "plugin-url")
|
||||
private String pluginUrl = DEFAULT_PLUGINURL;
|
||||
|
||||
/**
|
||||
* Login attempt timeout.
|
||||
*
|
||||
* @since 1.34
|
||||
*/
|
||||
@XmlElement(name = "login-attempt-limit-timeout")
|
||||
private long loginAttemptLimitTimeout = TimeUnit.MINUTES.toSeconds(5l);
|
||||
|
||||
/** @deprecated use {@link #baseUrl} and {@link #forceBaseUrl} */
|
||||
@Deprecated
|
||||
private boolean enableSSL = false;
|
||||
|
||||
/** Field description */
|
||||
private boolean enableProxy = false;
|
||||
|
||||
/** @deprecated use {@link #baseUrl} */
|
||||
@Deprecated
|
||||
private boolean enablePortForward = false;
|
||||
@@ -837,6 +871,13 @@ public class ScmConfiguration
|
||||
@Deprecated
|
||||
private int sslPort = 8181;
|
||||
|
||||
/**
|
||||
*
|
||||
* Authentication realm for basic authentication.
|
||||
*
|
||||
*/
|
||||
private String realmDescription = HttpUtil.AUTHENTICATION_REALM;
|
||||
|
||||
/** Configuration change listeners */
|
||||
@XmlTransient
|
||||
private Set<ConfigChangedListener> listeners =
|
||||
@@ -848,13 +889,6 @@ public class ScmConfiguration
|
||||
/** Field description */
|
||||
private boolean disableGroupingGrid = false;
|
||||
|
||||
/**
|
||||
*
|
||||
* Authentication realm for basic authentication.
|
||||
*
|
||||
*/
|
||||
private String realmDescription = HttpUtil.AUTHENTICATION_REALM;
|
||||
|
||||
/**
|
||||
* JavaScript date format from moment.js
|
||||
* @see <a href="http://momentjs.com/docs/#/parsing/" target="_blank">http://momentjs.com/docs/#/parsing/</a>
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.cache.Cache;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.security.EncryptionHandler;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
@@ -87,21 +88,24 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param userManager
|
||||
* @param authenticationHandlerSet
|
||||
* @param encryptionHandler
|
||||
* @param cacheManager
|
||||
* @param authenticationListenerProvider
|
||||
* @param authenticationListeners
|
||||
*/
|
||||
@Inject
|
||||
public ChainAuthenticatonManager(UserManager userManager,
|
||||
public ChainAuthenticatonManager(ScmConfiguration configuration,
|
||||
UserManager userManager,
|
||||
Set<AuthenticationHandler> authenticationHandlerSet,
|
||||
EncryptionHandler encryptionHandler, CacheManager cacheManager,
|
||||
Set<AuthenticationListener> authenticationListeners)
|
||||
{
|
||||
AssertUtil.assertIsNotEmpty(authenticationHandlerSet);
|
||||
AssertUtil.assertIsNotNull(cacheManager);
|
||||
this.configuration = configuration;
|
||||
this.authenticationHandlers = sort(userManager, authenticationHandlerSet);
|
||||
this.encryptionHandler = encryptionHandler;
|
||||
this.cache = cacheManager.getCache(String.class,
|
||||
@@ -200,6 +204,22 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param result
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean stopChain(AuthenticationResult result)
|
||||
{
|
||||
return (result != null) && (result.getState() != null)
|
||||
&& (result.getState().isSuccessfully()
|
||||
|| ((result.getState() == AuthenticationState.FAILED)
|
||||
&&!configuration.isSkipFailedAuthenticators()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -240,9 +260,7 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
|
||||
authenticator.getClass().getName(), result);
|
||||
}
|
||||
|
||||
if ((result != null) && (result.getState() != null)
|
||||
&& (result.getState().isSuccessfully()
|
||||
|| (result.getState() == AuthenticationState.FAILED)))
|
||||
if (stopChain(result))
|
||||
{
|
||||
if (result.getState().isSuccessfully() && (result.getUser() != null))
|
||||
{
|
||||
@@ -378,11 +396,14 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private List<AuthenticationHandler> authenticationHandlers;
|
||||
private final List<AuthenticationHandler> authenticationHandlers;
|
||||
|
||||
/** Field description */
|
||||
private Cache<String, AuthenticationCacheValue> cache;
|
||||
private final Cache<String, AuthenticationCacheValue> cache;
|
||||
|
||||
/** Field description */
|
||||
private EncryptionHandler encryptionHandler;
|
||||
private final ScmConfiguration configuration;
|
||||
|
||||
/** Field description */
|
||||
private final EncryptionHandler encryptionHandler;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
|
||||
errorSubmitMsgText: 'Could not submit config.',
|
||||
|
||||
// TODO i18n
|
||||
skipFailedAuthenticatorsText: 'Skip failed authenticators',
|
||||
loginAttemptLimitText: 'Login Attempt Limit',
|
||||
loginAttemptLimitTimeoutText: 'Login Attempt Limit Timeout',
|
||||
|
||||
@@ -85,6 +86,8 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
|
||||
adminUsersHelpText: 'Comma seperated list of users with admin permissions.',
|
||||
|
||||
// TODO i18n
|
||||
skipFailedAuthenticatorsHelpText: 'Do not stop the authentication chain, \n\
|
||||
if an authenticator finds the user but fails to authenticate the user.',
|
||||
loginAttemptLimitHelpText: 'Maximum allowed login attempts. Use -1 to disable the login attempt limit.',
|
||||
loginAttemptLimitTimeoutHelpText: 'Timeout in seconds for users which are temporary disabled,\
|
||||
because of too many failed login attempts.',
|
||||
@@ -157,6 +160,12 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
|
||||
name: 'anonymousAccessEnabled',
|
||||
inputValue: 'true',
|
||||
helpText: this.allowAnonymousAccessHelpText
|
||||
},{
|
||||
xtype: 'checkbox',
|
||||
fieldLabel: this.skipFailedAuthenticatorsText,
|
||||
name: 'skip-failed-authenticators',
|
||||
inputValue: 'true',
|
||||
helpText: this.skipFailedAuthenticatorsHelpText
|
||||
},{
|
||||
xtype: 'numberfield',
|
||||
fieldLabel: this.loginAttemptLimitText,
|
||||
|
||||
@@ -40,7 +40,7 @@ if (Ext.form.VTypes){
|
||||
passwordText: 'Die Passwörter stimmen nicht überein!',
|
||||
nameTest: 'Der Name ist invalid.',
|
||||
usernameText: 'Der Benutzername ist invalid.',
|
||||
repositoryNameText: 'Der Name des Repositorys ist ungültig.',
|
||||
repositoryNameText: 'Der Name des Repositorys ist ungültig.'
|
||||
});
|
||||
|
||||
}
|
||||
@@ -349,6 +349,10 @@ if (Sonia.config.ScmConfigPanel){
|
||||
adminGroupsHelpText: 'Komma getrennte Liste von Gruppen mit Administrationsrechten.',
|
||||
adminUsersHelpText: 'Komma getrennte Liste von Benutzern mit Administrationsrechten.',
|
||||
|
||||
skipFailedAuthenticatorsText: 'Überspringe fehlgeschlagene Authentifizierer',
|
||||
skipFailedAuthenticatorsHelpText: 'Setzt die Authentifizierungs-Kette fort,\n\
|
||||
auch wenn ein ein Authentifizierer einen Benutzer gefunden hat,\n\
|
||||
diesen aber nicht Authentifizieren kann.',
|
||||
loginAttemptLimitText: 'Login Attempt Limit',
|
||||
loginAttemptLimitTimeoutText: 'Login Attempt Limit Timeout',
|
||||
loginAttemptLimitHelpText: 'Maximale Anzahl gescheiterte Loginversuche. Der Wert -1 deaktiviert die Begrenzung.',
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.junit.Test;
|
||||
import sonia.scm.AbstractTestBase;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.cache.MapCacheManager;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.security.MessageDigestEncryptionHandler;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
@@ -137,7 +138,7 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
|
||||
SingleUserAuthenticaionHandler a2 =
|
||||
new SingleUserAuthenticaionHandler("a2", trillian);
|
||||
|
||||
manager = createManager("a2", a1, a2);
|
||||
manager = createManager("a2", false, a1, a2);
|
||||
|
||||
AuthenticationResult result = manager.authenticate(request, response,
|
||||
trillian.getName(), "trillian123");
|
||||
@@ -147,6 +148,24 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
|
||||
assertEquals("a2", result.getUser().getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testStopChain()
|
||||
{
|
||||
ChainAuthenticatonManager cam = createManager("", false);
|
||||
|
||||
assertTrue(cam.stopChain(new AuthenticationResult(perfect)));
|
||||
assertTrue(cam.stopChain(AuthenticationResult.FAILED));
|
||||
assertFalse(cam.stopChain(AuthenticationResult.NOT_FOUND));
|
||||
cam = createManager("", true);
|
||||
assertTrue(cam.stopChain(new AuthenticationResult(perfect)));
|
||||
assertFalse(cam.stopChain(AuthenticationResult.FAILED));
|
||||
assertFalse(cam.stopChain(AuthenticationResult.NOT_FOUND));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -199,7 +218,7 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
|
||||
trillian = UserTestData.createTrillian();
|
||||
trillian.setPassword("trillian123");
|
||||
|
||||
return createManager("",
|
||||
return createManager("", false,
|
||||
new SingleUserAuthenticaionHandler("perfectsType", perfect),
|
||||
new SingleUserAuthenticaionHandler("trilliansType", trillian));
|
||||
}
|
||||
@@ -209,20 +228,33 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
|
||||
*
|
||||
*
|
||||
* @param defaultType
|
||||
* @param skipFailedAuthenticators
|
||||
* @param handlers
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ChainAuthenticatonManager createManager(String defaultType,
|
||||
AuthenticationHandler... handlers)
|
||||
boolean skipFailedAuthenticators, AuthenticationHandler... handlers)
|
||||
{
|
||||
if ( handlers == null || handlers.length == 0 ){
|
||||
//J-
|
||||
handlers = new AuthenticationHandler[]{
|
||||
new SingleUserAuthenticaionHandler("perfectsType", perfect),
|
||||
new SingleUserAuthenticaionHandler("trilliansType", trillian)
|
||||
};
|
||||
//J+
|
||||
}
|
||||
ScmConfiguration configuration = new ScmConfiguration();
|
||||
|
||||
configuration.setSkipFailedAuthenticators(skipFailedAuthenticators);
|
||||
|
||||
Set<AuthenticationHandler> handlerSet = ImmutableSet.copyOf(handlers);
|
||||
|
||||
UserManager userManager = mock(UserManager.class);
|
||||
|
||||
when(userManager.getDefaultType()).thenReturn(defaultType);
|
||||
manager = new ChainAuthenticatonManager(userManager, handlerSet,
|
||||
new MessageDigestEncryptionHandler(), new MapCacheManager(),
|
||||
manager = new ChainAuthenticatonManager(configuration, userManager,
|
||||
handlerSet, new MessageDigestEncryptionHandler(), new MapCacheManager(),
|
||||
Collections.EMPTY_SET);
|
||||
manager.init(contextProvider);
|
||||
|
||||
@@ -328,10 +360,10 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String type;
|
||||
private final String type;
|
||||
|
||||
/** Field description */
|
||||
private User user;
|
||||
private final User user;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user