Update Deprecated Spring Jdbc Usage

This commit is contained in:
Josh Cummings 2025-04-22 14:34:22 -06:00
parent 2ad859a63c
commit 216680bb50
No known key found for this signature in database
GPG Key ID: 869B37A20E876129
6 changed files with 55 additions and 43 deletions

View File

@ -100,8 +100,8 @@ public class JdbcAclService implements AclService {
@Override @Override
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) { public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() }; Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() };
List<ObjectIdentity> objects = this.jdbcOperations.query(this.findChildrenSql, args, List<ObjectIdentity> objects = this.jdbcOperations.query(this.findChildrenSql,
(rs, rowNum) -> mapObjectIdentityRow(rs)); (rs, rowNum) -> mapObjectIdentityRow(rs), args);
return (!objects.isEmpty()) ? objects : null; return (!objects.isEmpty()) ? objects : null;
} }

View File

@ -190,8 +190,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @return the primary key or null if not found * @return the primary key or null if not found
*/ */
protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) { protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
List<Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, new Object[] { type }, List<Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, Long.class, type);
Long.class);
if (!classIds.isEmpty()) { if (!classIds.isEmpty()) {
return classIds.get(0); return classIds.get(0);
@ -242,8 +241,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @return the primary key or null if not found * @return the primary key or null if not found
*/ */
protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) { protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) {
List<Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, List<Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, Long.class, sidIsPrincipal,
new Object[] { sidIsPrincipal, sidName }, Long.class); sidName);
if (!sidIds.isEmpty()) { if (!sidIds.isEmpty()) {
return sidIds.get(0); return sidIds.get(0);
} }

View File

@ -109,7 +109,7 @@ public class JdbcAclServiceTests {
List<ObjectIdentity> result = new ArrayList<>(); List<ObjectIdentity> result = new ArrayList<>();
result.add(new ObjectIdentityImpl(Object.class, "5577")); result.add(new ObjectIdentityImpl(Object.class, "5577"));
Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" }; Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" };
given(this.jdbcOperations.query(anyString(), eq(args), any(RowMapper.class))).willReturn(result); given(this.jdbcOperations.query(anyString(), any(RowMapper.class), eq(args))).willReturn(result);
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L); ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
List<ObjectIdentity> objectIdentities = this.aclService.findChildren(objectIdentity); List<ObjectIdentity> objectIdentities = this.aclService.findChildren(objectIdentity);
assertThat(objectIdentities).hasSize(1); assertThat(objectIdentities).hasSize(1);

View File

@ -226,10 +226,10 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService, M
* @return a list of GrantedAuthority objects for the user * @return a list of GrantedAuthority objects for the user
*/ */
protected List<GrantedAuthority> loadUserAuthorities(String username) { protected List<GrantedAuthority> loadUserAuthorities(String username) {
return getJdbcTemplate().query(this.authoritiesByUsernameQuery, new String[] { username }, (rs, rowNum) -> { return getJdbcTemplate().query(this.authoritiesByUsernameQuery, (rs, rowNum) -> {
String roleName = JdbcDaoImpl.this.rolePrefix + rs.getString(2); String roleName = JdbcDaoImpl.this.rolePrefix + rs.getString(2);
return new SimpleGrantedAuthority(roleName); return new SimpleGrantedAuthority(roleName);
}); }, username);
} }
/** /**
@ -238,11 +238,10 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService, M
* @return a list of GrantedAuthority objects for the user * @return a list of GrantedAuthority objects for the user
*/ */
protected List<GrantedAuthority> loadGroupAuthorities(String username) { protected List<GrantedAuthority> loadGroupAuthorities(String username) {
return getJdbcTemplate().query(this.groupAuthoritiesByUsernameQuery, new String[] { username }, return getJdbcTemplate().query(this.groupAuthoritiesByUsernameQuery, (rs, rowNum) -> {
(rs, rowNum) -> { String roleName = getRolePrefix() + rs.getString(3);
String roleName = getRolePrefix() + rs.getString(3); return new SimpleGrantedAuthority(roleName);
return new SimpleGrantedAuthority(roleName); }, username);
});
} }
/** /**

View File

@ -336,8 +336,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
@Override @Override
public boolean userExists(String username) { public boolean userExists(String username) {
List<String> users = getJdbcTemplate().queryForList(this.userExistsSql, new String[] { username }, List<String> users = getJdbcTemplate().queryForList(this.userExistsSql, String.class, username);
String.class);
if (users.size() > 1) { if (users.size() > 1) {
throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'",
1); 1);
@ -353,7 +352,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
@Override @Override
public List<String> findUsersInGroup(String groupName) { public List<String> findUsersInGroup(String groupName) {
Assert.hasText(groupName, "groupName should have text"); Assert.hasText(groupName, "groupName should have text");
return getJdbcTemplate().queryForList(this.findUsersInGroupSql, new String[] { groupName }, String.class); return getJdbcTemplate().queryForList(this.findUsersInGroupSql, String.class, groupName);
} }
@Override @Override
@ -422,8 +421,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
public List<GrantedAuthority> findGroupAuthorities(String groupName) { public List<GrantedAuthority> findGroupAuthorities(String groupName) {
this.logger.debug("Loading authorities for group '" + groupName + "'"); this.logger.debug("Loading authorities for group '" + groupName + "'");
Assert.hasText(groupName, "groupName should have text"); Assert.hasText(groupName, "groupName should have text");
return getJdbcTemplate().query(this.groupAuthoritiesSql, new String[] { groupName }, return getJdbcTemplate().query(this.groupAuthoritiesSql, this.grantedAuthorityMapper, groupName);
this.grantedAuthorityMapper);
} }
private GrantedAuthority mapToGrantedAuthority(ResultSet rs, int rowNum) throws SQLException { private GrantedAuthority mapToGrantedAuthority(ResultSet rs, int rowNum) throws SQLException {

View File

@ -33,7 +33,6 @@ import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameterValue; import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobCreator; import org.springframework.jdbc.support.lob.LobCreator;
import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport; import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
@ -62,11 +61,11 @@ import org.springframework.util.CollectionUtils;
*/ */
public final class JdbcUserCredentialRepository implements UserCredentialRepository { public final class JdbcUserCredentialRepository implements UserCredentialRepository {
private RowMapper<CredentialRecord> credentialRecordRowMapper = new CredentialRecordRowMapper(); private RowMapper<CredentialRecord> credentialRecordRowMapper = new CredentialRecordRowMapper(ResultSet::getBytes);
private Function<CredentialRecord, List<SqlParameterValue>> credentialRecordParametersMapper = new CredentialRecordParametersMapper(); private Function<CredentialRecord, List<SqlParameterValue>> credentialRecordParametersMapper = new CredentialRecordParametersMapper();
private LobHandler lobHandler = new DefaultLobHandler(); private SetBytes setBytes = PreparedStatement::setBytes;
private final JdbcOperations jdbcOperations; private final JdbcOperations jdbcOperations;
@ -159,22 +158,16 @@ public final class JdbcUserCredentialRepository implements UserCredentialReposit
private void insertCredentialRecord(CredentialRecord record) { private void insertCredentialRecord(CredentialRecord record) {
List<SqlParameterValue> parameters = this.credentialRecordParametersMapper.apply(record); List<SqlParameterValue> parameters = this.credentialRecordParametersMapper.apply(record);
try (LobCreator lobCreator = this.lobHandler.getLobCreator()) { PreparedStatementSetter pss = new BlobArgumentPreparedStatementSetter(this.setBytes, parameters.toArray());
PreparedStatementSetter pss = new LobCreatorArgumentPreparedStatementSetter(lobCreator, this.jdbcOperations.update(SAVE_CREDENTIAL_RECORD_SQL, pss);
parameters.toArray());
this.jdbcOperations.update(SAVE_CREDENTIAL_RECORD_SQL, pss);
}
} }
private int updateCredentialRecord(CredentialRecord record) { private int updateCredentialRecord(CredentialRecord record) {
List<SqlParameterValue> parameters = this.credentialRecordParametersMapper.apply(record); List<SqlParameterValue> parameters = this.credentialRecordParametersMapper.apply(record);
SqlParameterValue credentialId = parameters.remove(0); SqlParameterValue credentialId = parameters.remove(0);
parameters.add(credentialId); parameters.add(credentialId);
try (LobCreator lobCreator = this.lobHandler.getLobCreator()) { PreparedStatementSetter pss = new BlobArgumentPreparedStatementSetter(this.setBytes, parameters.toArray());
PreparedStatementSetter pss = new LobCreatorArgumentPreparedStatementSetter(lobCreator, return this.jdbcOperations.update(UPDATE_CREDENTIAL_RECORD_SQL, pss);
parameters.toArray());
return this.jdbcOperations.update(UPDATE_CREDENTIAL_RECORD_SQL, pss);
}
} }
@Override @Override
@ -195,10 +188,18 @@ public final class JdbcUserCredentialRepository implements UserCredentialReposit
/** /**
* Sets a {@link LobHandler} for large binary fields and large text field parameters. * Sets a {@link LobHandler} for large binary fields and large text field parameters.
* @param lobHandler the lob handler * @param lobHandler the lob handler
* @deprecated {@link LobHandler} is deprecated without replacement, as such this
* method will also be removed without replacement
*/ */
@Deprecated(since = "6.5", forRemoval = true)
public void setLobHandler(LobHandler lobHandler) { public void setLobHandler(LobHandler lobHandler) {
Assert.notNull(lobHandler, "lobHandler cannot be null"); Assert.notNull(lobHandler, "lobHandler cannot be null");
this.lobHandler = lobHandler; this.setBytes = (ps, index, bytes) -> {
try (LobCreator creator = lobHandler.getLobCreator()) {
creator.setBlobAsBytes(ps, index, bytes);
}
};
this.credentialRecordRowMapper = new CredentialRecordRowMapper(lobHandler::getBlobAsBytes);
} }
private static class CredentialRecordParametersMapper private static class CredentialRecordParametersMapper
@ -246,13 +247,25 @@ public final class JdbcUserCredentialRepository implements UserCredentialReposit
} }
private static final class LobCreatorArgumentPreparedStatementSetter extends ArgumentPreparedStatementSetter { private interface SetBytes {
private final LobCreator lobCreator; void setBytes(PreparedStatement ps, int index, byte[] bytes) throws SQLException;
private LobCreatorArgumentPreparedStatementSetter(LobCreator lobCreator, Object[] args) { }
private interface GetBytes {
byte[] getBytes(ResultSet rs, String columnName) throws SQLException;
}
private static final class BlobArgumentPreparedStatementSetter extends ArgumentPreparedStatementSetter {
private final SetBytes setBytes;
private BlobArgumentPreparedStatementSetter(SetBytes setBytes, Object[] args) {
super(args); super(args);
this.lobCreator = lobCreator; this.setBytes = setBytes;
} }
@Override @Override
@ -264,7 +277,7 @@ public final class JdbcUserCredentialRepository implements UserCredentialReposit
"Value of blob parameter must be byte[]"); "Value of blob parameter must be byte[]");
} }
byte[] valueBytes = (byte[]) paramValue.getValue(); byte[] valueBytes = (byte[]) paramValue.getValue();
this.lobCreator.setBlobAsBytes(ps, parameterPosition, valueBytes); this.setBytes.setBytes(ps, parameterPosition, valueBytes);
return; return;
} }
} }
@ -275,14 +288,17 @@ public final class JdbcUserCredentialRepository implements UserCredentialReposit
private static class CredentialRecordRowMapper implements RowMapper<CredentialRecord> { private static class CredentialRecordRowMapper implements RowMapper<CredentialRecord> {
private LobHandler lobHandler = new DefaultLobHandler(); private final GetBytes getBytes;
CredentialRecordRowMapper(GetBytes getBytes) {
this.getBytes = getBytes;
}
@Override @Override
public CredentialRecord mapRow(ResultSet rs, int rowNum) throws SQLException { public CredentialRecord mapRow(ResultSet rs, int rowNum) throws SQLException {
Bytes credentialId = Bytes.fromBase64(new String(rs.getString("credential_id").getBytes())); Bytes credentialId = Bytes.fromBase64(new String(rs.getString("credential_id").getBytes()));
Bytes userEntityUserId = Bytes.fromBase64(new String(rs.getString("user_entity_user_id").getBytes())); Bytes userEntityUserId = Bytes.fromBase64(new String(rs.getString("user_entity_user_id").getBytes()));
ImmutablePublicKeyCose publicKey = new ImmutablePublicKeyCose( ImmutablePublicKeyCose publicKey = new ImmutablePublicKeyCose(this.getBytes.getBytes(rs, "public_key"));
this.lobHandler.getBlobAsBytes(rs, "public_key"));
long signatureCount = rs.getLong("signature_count"); long signatureCount = rs.getLong("signature_count");
boolean uvInitialized = rs.getBoolean("uv_initialized"); boolean uvInitialized = rs.getBoolean("uv_initialized");
boolean backupEligible = rs.getBoolean("backup_eligible"); boolean backupEligible = rs.getBoolean("backup_eligible");
@ -291,13 +307,13 @@ public final class JdbcUserCredentialRepository implements UserCredentialReposit
boolean backupState = rs.getBoolean("backup_state"); boolean backupState = rs.getBoolean("backup_state");
Bytes attestationObject = null; Bytes attestationObject = null;
byte[] rawAttestationObject = this.lobHandler.getBlobAsBytes(rs, "attestation_object"); byte[] rawAttestationObject = this.getBytes.getBytes(rs, "attestation_object");
if (rawAttestationObject != null) { if (rawAttestationObject != null) {
attestationObject = new Bytes(rawAttestationObject); attestationObject = new Bytes(rawAttestationObject);
} }
Bytes attestationClientDataJson = null; Bytes attestationClientDataJson = null;
byte[] rawAttestationClientDataJson = this.lobHandler.getBlobAsBytes(rs, "attestation_client_data_json"); byte[] rawAttestationClientDataJson = this.getBytes.getBytes(rs, "attestation_client_data_json");
if (rawAttestationClientDataJson != null) { if (rawAttestationClientDataJson != null) {
attestationClientDataJson = new Bytes(rawAttestationClientDataJson); attestationClientDataJson = new Bytes(rawAttestationClientDataJson);
} }