Class LegacyAwareDaoAuthenticationProvider
java.lang.Object
org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider
org.springframework.security.authentication.dao.DaoAuthenticationProvider
ubic.gemma.core.security.authentication.LegacyAwareDaoAuthenticationProvider
- All Implemented Interfaces:
org.springframework.beans.factory.Aware, org.springframework.beans.factory.InitializingBean, org.springframework.context.MessageSourceAware, org.springframework.security.authentication.AuthenticationProvider
public class LegacyAwareDaoAuthenticationProvider
extends org.springframework.security.authentication.dao.DaoAuthenticationProvider
DaoAuthenticationProvider that understands Gemma's two pre-Phase-2 legacy
password formats, both bare 40-char hex SHA-1 with no prefix:
- Username-salt (post-2009-11-23):
SHA-1(rawPassword + "{" + username + "}")— configured via<s:salt-source user-property="username"/>. Seesql/init-data.sql. - Fixed system-wide salt (pre-2009-11-23):
SHA-1(rawPassword + "{gooblyfoobly}")— configured viaSystemWideSaltSourcewithgemma.salt=gooblyfooblyin build.properties (commit66f574e926, 2008-10-02). Users created before the 2009 salt-source switch (notably the originaladministratoraccount) still have hashes in this format in production gemd if their password hasn't been rotated.
The two are structurally indistinguishable (both 40-char SHA-1 hex), so verification tries username-salt first, then fixed-salt; only if both miss is the password rejected.
For any other stored hash format ({bcrypt}-prefixed or bare BCrypt are the
currently supported alternatives) verification falls through to the stock
DaoAuthenticationProvider machinery, which delegates to the configured
PasswordEncoder
(GemmaLegacyAwarePasswordEncoder).
Why this exists (Phase 3 cloud-readiness)
Spring Security 6'sPasswordEncoder interface is username-agnostic and the
username-as-salt scheme requires the username at verify time. The previous Phase-2
implementation pushed the username through a ThreadLocal on the encoder before
super.additionalAuthenticationChecks ran. That ThreadLocal is hostile to async /
reactive flows and per-request thread reuse, which is why it has been removed.
Now the legacy SHA-1 verification happens here, with the authoritative username sourced
from userDetails.getUsername() (loaded by
UserDetailsService) — no
thread-bound state of any kind.
Password upgrade flow
AfteradditionalAuthenticationChecks returns successfully, the stock
DaoAuthenticationProvider.authenticate(...) does:
if (passwordEncoder.upgradeEncoding(user.getPassword())) {
String newPassword = passwordEncoder.encode(presented);
user = userDetailsPasswordService.updatePassword(user, newPassword);
}
GemmaLegacyAwarePasswordEncoder.upgradeEncoding(String) returns true for legacy
hashes, so a legacy match here triggers an automatic re-encode to {bcrypt} and a
write-back via UserManagerImpl (which implements UserDetailsPasswordService).- Author:
- Gemma
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringHistorical SystemWideSaltSource value frombuild.properties(commit66f574e926, 2008-10-02).Fields inherited from class org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider
hideUserNotFoundExceptions, logger, messages -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voidadditionalAuthenticationChecks(org.springframework.security.core.userdetails.UserDetails userDetails, org.springframework.security.authentication.UsernamePasswordAuthenticationToken authentication) voidsetSystemWideSalt(String salt) Override the system-wide salt used for the pre-2009 fixed-salt fallback.Methods inherited from class org.springframework.security.authentication.dao.DaoAuthenticationProvider
createSuccessAuthentication, doAfterPropertiesSet, getPasswordEncoder, getUserDetailsService, retrieveUser, setCompromisedPasswordChecker, setPasswordEncoder, setUserDetailsPasswordService, setUserDetailsServiceMethods inherited from class org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider
afterPropertiesSet, authenticate, getPostAuthenticationChecks, getPreAuthenticationChecks, getUserCache, isForcePrincipalAsString, isHideUserNotFoundExceptions, setAlwaysPerformAdditionalChecksOnUser, setAuthoritiesMapper, setForcePrincipalAsString, setHideUserNotFoundExceptions, setMessageSource, setPostAuthenticationChecks, setPreAuthenticationChecks, setUserCache, supports
-
Field Details
-
SYSTEM_WIDE_SALT
Historical SystemWideSaltSource value frombuild.properties(commit66f574e926, 2008-10-02). Used by theadministratorrow and any other account whose password has not been rotated since the 2009-11-23 switch to username-salt. Default; override viasetSystemWideSalt(String)(or thegemma.legacy.saltproperty if Spring-wired) if the production salt has been rotated since 2008.- See Also:
-
-
Constructor Details
-
LegacyAwareDaoAuthenticationProvider
public LegacyAwareDaoAuthenticationProvider()
-
-
Method Details
-
setSystemWideSalt
Override the system-wide salt used for the pre-2009 fixed-salt fallback. Setter form so Spring can inject from a property without restructuring the constructor. -
getSystemWideSalt
-
additionalAuthenticationChecks
protected void additionalAuthenticationChecks(org.springframework.security.core.userdetails.UserDetails userDetails, org.springframework.security.authentication.UsernamePasswordAuthenticationToken authentication) throws org.springframework.security.core.AuthenticationException - Overrides:
additionalAuthenticationChecksin classorg.springframework.security.authentication.dao.DaoAuthenticationProvider- Throws:
org.springframework.security.core.AuthenticationException
-