Skip to content

Commit fb0c706

Browse files
committed
Get rid of deprecated JdbcDaoSupport
Signed-off-by: Yanming Zhou <[email protected]>
1 parent 5da2121 commit fb0c706

File tree

5 files changed

+141
-29
lines changed

5 files changed

+141
-29
lines changed

core/src/main/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@
2121
import java.util.List;
2222
import java.util.Set;
2323

24-
import org.springframework.context.ApplicationContextException;
24+
import javax.sql.DataSource;
25+
26+
import org.apache.commons.logging.Log;
27+
import org.apache.commons.logging.LogFactory;
28+
import org.jspecify.annotations.Nullable;
29+
30+
import org.springframework.beans.factory.BeanInitializationException;
31+
import org.springframework.beans.factory.InitializingBean;
2532
import org.springframework.context.MessageSource;
2633
import org.springframework.context.MessageSourceAware;
2734
import org.springframework.context.support.MessageSourceAccessor;
2835
import org.springframework.jdbc.core.JdbcTemplate;
2936
import org.springframework.jdbc.core.RowMapper;
30-
import org.springframework.jdbc.core.support.JdbcDaoSupport;
3137
import org.springframework.security.core.GrantedAuthority;
3238
import org.springframework.security.core.SpringSecurityMessageSource;
3339
import org.springframework.security.core.authority.AuthorityUtils;
@@ -108,8 +114,9 @@
108114
* @author Ben Alex
109115
* @author colin sampaleanu
110116
* @author Luke Taylor
117+
* @author Yanming Zhou
111118
*/
112-
public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService, MessageSourceAware {
119+
public class JdbcDaoImpl implements UserDetailsService, MessageSourceAware, InitializingBean {
113120

114121
public static final String DEFAULT_USER_SCHEMA_DDL_LOCATION = "org/springframework/security/core/userdetails/jdbc/users.ddl";
115122

@@ -131,6 +138,10 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService, M
131138
+ "where gm.username = ? " + "and g.id = ga.group_id " + "and g.id = gm.group_id";
132139
// @formatter:on
133140

141+
protected final Log logger = LogFactory.getLog(getClass());
142+
143+
private @Nullable JdbcTemplate jdbcTemplate;
144+
134145
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
135146

136147
private String authoritiesByUsernameQuery;
@@ -153,6 +164,60 @@ public JdbcDaoImpl() {
153164
this.groupAuthoritiesByUsernameQuery = DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY;
154165
}
155166

167+
/**
168+
* Set the JDBC DataSource to be used by this DAO.
169+
*/
170+
public final void setDataSource(DataSource dataSource) {
171+
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
172+
this.jdbcTemplate = new JdbcTemplate(dataSource);
173+
}
174+
}
175+
176+
public final @Nullable DataSource getDataSource() {
177+
return (this.jdbcTemplate != null) ? this.jdbcTemplate.getDataSource() : null;
178+
}
179+
180+
/**
181+
* Set the JdbcTemplate for this DAO explicitly, as an alternative to specifying a
182+
* DataSource.
183+
*/
184+
public final void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
185+
this.jdbcTemplate = jdbcTemplate;
186+
}
187+
188+
/**
189+
* Return the JdbcTemplate for this DAO, pre-initialized with the DataSource or set
190+
* explicitly.
191+
*/
192+
public final @Nullable JdbcTemplate getJdbcTemplate() {
193+
return this.jdbcTemplate;
194+
}
195+
196+
@Override
197+
public final void afterPropertiesSet() {
198+
// Let abstract subclasses check their configuration.
199+
checkDaoConfig();
200+
201+
// Let concrete implementations initialize themselves.
202+
try {
203+
initDao();
204+
}
205+
catch (Exception ex) {
206+
throw new BeanInitializationException("Initialization of DAO failed", ex);
207+
}
208+
}
209+
210+
protected void checkDaoConfig() {
211+
if (this.jdbcTemplate == null) {
212+
throw new IllegalArgumentException("'dataSource' or 'jdbcTemplate' is required");
213+
}
214+
}
215+
216+
protected void initDao() {
217+
Assert.isTrue(this.enableAuthorities || this.enableGroups,
218+
"Use of either authorities or groups must be enabled");
219+
}
220+
156221
/**
157222
* @return the messages
158223
*/
@@ -174,12 +239,6 @@ public String getUsersByUsernameQuery() {
174239
return this.usersByUsernameQuery;
175240
}
176241

177-
@Override
178-
protected void initDao() throws ApplicationContextException {
179-
Assert.isTrue(this.enableAuthorities || this.enableGroups,
180-
"Use of either authorities or groups must be enabled");
181-
}
182-
183242
@Override
184243
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
185244
List<UserDetails> users = loadUsersByUsername(username);
@@ -219,15 +278,15 @@ protected List<UserDetails> loadUsersByUsername(String username) {
219278
return new User(username1, password, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES);
220279
};
221280
// @formatter:on
222-
return getJdbc().query(this.usersByUsernameQuery, mapper, username);
281+
return requireJdbcTemplate().query(this.usersByUsernameQuery, mapper, username);
223282
}
224283

225284
/**
226285
* Loads authorities by executing the SQL from <tt>authoritiesByUsernameQuery</tt>.
227286
* @return a list of GrantedAuthority objects for the user
228287
*/
229288
protected List<GrantedAuthority> loadUserAuthorities(String username) {
230-
return getJdbc().query(this.authoritiesByUsernameQuery, (rs, rowNum) -> {
289+
return requireJdbcTemplate().query(this.authoritiesByUsernameQuery, (rs, rowNum) -> {
231290
String roleName = JdbcDaoImpl.this.rolePrefix + rs.getString(2);
232291
return new SimpleGrantedAuthority(roleName);
233292
}, username);
@@ -239,7 +298,7 @@ protected List<GrantedAuthority> loadUserAuthorities(String username) {
239298
* @return a list of GrantedAuthority objects for the user
240299
*/
241300
protected List<GrantedAuthority> loadGroupAuthorities(String username) {
242-
return getJdbc().query(this.groupAuthoritiesByUsernameQuery, (rs, rowNum) -> {
301+
return requireJdbcTemplate().query(this.groupAuthoritiesByUsernameQuery, (rs, rowNum) -> {
243302
String roleName = getRolePrefix() + rs.getString(3);
244303
return new SimpleGrantedAuthority(roleName);
245304
}, username);
@@ -375,8 +434,8 @@ public void setMessageSource(MessageSource messageSource) {
375434
this.messages = new MessageSourceAccessor(messageSource);
376435
}
377436

378-
private JdbcTemplate getJdbc() {
379-
JdbcTemplate template = getJdbcTemplate();
437+
protected JdbcTemplate requireJdbcTemplate() {
438+
JdbcTemplate template = this.jdbcTemplate;
380439
Assert.notNull(template, "JdbcTemplate cannot be null");
381440
return template;
382441
}

core/src/main/java/org/springframework/security/provisioning/JdbcUserDetailsManager.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@
2727
import org.apache.commons.logging.LogFactory;
2828
import org.jspecify.annotations.Nullable;
2929

30-
import org.springframework.context.ApplicationContextException;
3130
import org.springframework.core.log.LogMessage;
3231
import org.springframework.dao.EmptyResultDataAccessException;
3332
import org.springframework.dao.IncorrectResultSizeDataAccessException;
34-
import org.springframework.jdbc.core.JdbcTemplate;
3533
import org.springframework.jdbc.core.PreparedStatementSetter;
3634
import org.springframework.jdbc.core.RowMapper;
3735
import org.springframework.security.access.AccessDeniedException;
@@ -67,6 +65,7 @@
6765
*
6866
* @author Luke Taylor
6967
* @author Junhyeok Lee
68+
* @author Yanming Zhou
7069
* @since 2.0
7170
*/
7271
public class JdbcUserDetailsManager extends JdbcDaoImpl
@@ -209,7 +208,7 @@ public void setGrantedAuthorityMapper(RowMapper<GrantedAuthority> mapper) {
209208
}
210209

211210
@Override
212-
protected void initDao() throws ApplicationContextException {
211+
protected void initDao() {
213212
if (this.authenticationManager == null) {
214213
this.logger.info(
215214
"No authentication manager set. Reauthentication of users when changing passwords will not be performed.");
@@ -471,12 +470,6 @@ private int findGroupId(String group) {
471470
return groupId;
472471
}
473472

474-
private JdbcTemplate requireJdbcTemplate() {
475-
JdbcTemplate jdbc = getJdbcTemplate();
476-
Assert.notNull(jdbc, "JdbcTemplate cannot be null");
477-
return jdbc;
478-
}
479-
480473
/**
481474
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
482475
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.

core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
* @author Luke Taylor
6363
* @author dae won
6464
* @author Junhyeok Lee
65+
* @author Yanming Zhou
6566
*/
6667
public class JdbcUserDetailsManagerTests {
6768

@@ -104,7 +105,7 @@ public void initializeManagerAndCreateTables() {
104105
this.manager.setDeleteUserAuthoritiesSql(JdbcUserDetailsManager.DEF_DELETE_USER_AUTHORITIES_SQL);
105106
this.manager.setDeleteUserSql(JdbcUserDetailsManager.DEF_DELETE_USER_SQL);
106107
this.manager.setChangePasswordSql(JdbcUserDetailsManager.DEF_CHANGE_PASSWORD_SQL);
107-
this.manager.initDao();
108+
this.manager.afterPropertiesSet();
108109
this.template = this.manager.getJdbcTemplate();
109110
this.template.execute("create table users(username varchar(20) not null primary key,"
110111
+ "password varchar(20) not null, enabled boolean not null)");

web/src/main/java/org/springframework/security/web/authentication/rememberme/JdbcTokenRepositoryImpl.java

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,28 @@
2020
import java.sql.SQLException;
2121
import java.util.Date;
2222

23+
import javax.sql.DataSource;
24+
25+
import org.apache.commons.logging.Log;
26+
import org.apache.commons.logging.LogFactory;
2327
import org.jspecify.annotations.Nullable;
2428

29+
import org.springframework.beans.factory.BeanInitializationException;
30+
import org.springframework.beans.factory.InitializingBean;
2531
import org.springframework.core.log.LogMessage;
2632
import org.springframework.dao.DataAccessException;
2733
import org.springframework.dao.EmptyResultDataAccessException;
2834
import org.springframework.dao.IncorrectResultSizeDataAccessException;
2935
import org.springframework.jdbc.core.JdbcTemplate;
30-
import org.springframework.jdbc.core.support.JdbcDaoSupport;
3136

3237
/**
3338
* JDBC based persistent login token repository implementation.
3439
*
3540
* @author Luke Taylor
41+
* @author Yanming Zhou
3642
* @since 2.0
3743
*/
38-
public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements PersistentTokenRepository {
44+
public class JdbcTokenRepositoryImpl implements PersistentTokenRepository, InitializingBean {
3945

4046
/** Default SQL for creating the database table to store the tokens */
4147
public static final String CREATE_TABLE_SQL = "create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, "
@@ -53,6 +59,10 @@ public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements Persisten
5359
/** The default SQL used by <tt>removeUserTokens</tt> */
5460
public static final String DEF_REMOVE_USER_TOKENS_SQL = "delete from persistent_logins where username = ?";
5561

62+
protected final Log logger = LogFactory.getLog(getClass());
63+
64+
private @Nullable JdbcTemplate jdbcTemplate;
65+
5666
private String tokensBySeriesSql = DEF_TOKEN_BY_SERIES_SQL;
5767

5868
private String insertTokenSql = DEF_INSERT_TOKEN_SQL;
@@ -64,6 +74,54 @@ public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements Persisten
6474
private boolean createTableOnStartup;
6575

6676
@Override
77+
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
78+
// Let abstract subclasses check their configuration.
79+
checkDaoConfig();
80+
81+
// Let concrete implementations initialize themselves.
82+
try {
83+
initDao();
84+
}
85+
catch (Exception ex) {
86+
throw new BeanInitializationException("Initialization of DAO failed", ex);
87+
}
88+
}
89+
90+
/**
91+
* Set the JDBC DataSource to be used by this DAO.
92+
*/
93+
public final void setDataSource(DataSource dataSource) {
94+
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
95+
this.jdbcTemplate = new JdbcTemplate(dataSource);
96+
}
97+
}
98+
99+
public final @Nullable DataSource getDataSource() {
100+
return (this.jdbcTemplate != null) ? this.jdbcTemplate.getDataSource() : null;
101+
}
102+
103+
/**
104+
* Set the JdbcTemplate for this DAO explicitly, as an alternative to specifying a
105+
* DataSource.
106+
*/
107+
public final void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
108+
this.jdbcTemplate = jdbcTemplate;
109+
}
110+
111+
/**
112+
* Return the JdbcTemplate for this DAO, pre-initialized with the DataSource or set
113+
* explicitly.
114+
*/
115+
public final @Nullable JdbcTemplate getJdbcTemplate() {
116+
return this.jdbcTemplate;
117+
}
118+
119+
protected void checkDaoConfig() {
120+
if (this.jdbcTemplate == null) {
121+
throw new IllegalArgumentException("'dataSource' or 'jdbcTemplate' is required");
122+
}
123+
}
124+
67125
protected void initDao() {
68126
if (this.createTableOnStartup) {
69127
getTemplate().execute(CREATE_TABLE_SQL);
@@ -128,7 +186,7 @@ public void setCreateTableOnStartup(boolean createTableOnStartup) {
128186
}
129187

130188
private JdbcTemplate getTemplate() {
131-
@Nullable JdbcTemplate result = super.getJdbcTemplate();
189+
@Nullable JdbcTemplate result = this.jdbcTemplate;
132190
if (result == null) {
133191
throw new IllegalStateException("JdbcTemplate was removed");
134192
}

web/src/test/java/org/springframework/security/web/authentication/rememberme/JdbcTokenRepositoryImplTests.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848

4949
/**
5050
* @author Luke Taylor
51+
* @author Yanming Zhou
5152
*/
5253
@ExtendWith(MockitoExtension.class)
5354
public class JdbcTokenRepositoryImplTests {
@@ -78,7 +79,7 @@ public void populateDatabase() {
7879
this.repo = new JdbcTokenRepositoryImpl();
7980
ReflectionTestUtils.setField(this.repo, "logger", this.logger);
8081
this.repo.setDataSource(dataSource);
81-
this.repo.initDao();
82+
this.repo.afterPropertiesSet();
8283
this.template = this.repo.getJdbcTemplate();
8384
this.template.execute("create table persistent_logins (username varchar(100) not null, "
8485
+ "series varchar(100) not null, token varchar(500) not null, last_used timestamp not null)");
@@ -170,7 +171,7 @@ public void createTableOnStartupCreatesCorrectTable() {
170171
this.repo = new JdbcTokenRepositoryImpl();
171172
this.repo.setDataSource(dataSource);
172173
this.repo.setCreateTableOnStartup(true);
173-
this.repo.initDao();
174+
this.repo.afterPropertiesSet();
174175
this.template.queryForList("select username,series,token,last_used from persistent_logins");
175176
}
176177

0 commit comments

Comments
 (0)