Skip to content

Commit e8f920e

Browse files
committed
Polish JdbcAssertingPartyMetadataRepository
- Remove GetBytes since it's not used yet - Remove customizable RowMapper since this can be added later - Change signing_algorithms to be a String since the conversion strategy is simple - Standardize test names - Simplify conversion of credentials using ThrowingFunction - Change column names to match RelyingPartyRegistration field names Issue gh-16012
1 parent 2bd0512 commit e8f920e

File tree

4 files changed

+63
-117
lines changed

4 files changed

+63
-117
lines changed

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/JdbcAssertingPartyMetadataRepository.java

Lines changed: 39 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@
2020
import java.sql.SQLException;
2121
import java.sql.Types;
2222
import java.util.ArrayList;
23+
import java.util.Arrays;
2324
import java.util.Collection;
25+
import java.util.Collections;
2426
import java.util.Iterator;
2527
import java.util.List;
2628
import java.util.function.Function;
2729

28-
import org.apache.commons.logging.Log;
29-
import org.apache.commons.logging.LogFactory;
30-
31-
import org.springframework.core.log.LogMessage;
3230
import org.springframework.core.serializer.DefaultDeserializer;
3331
import org.springframework.core.serializer.DefaultSerializer;
3432
import org.springframework.core.serializer.Deserializer;
@@ -53,53 +51,46 @@ public final class JdbcAssertingPartyMetadataRepository implements AssertingPart
5351

5452
private final JdbcOperations jdbcOperations;
5553

56-
private RowMapper<AssertingPartyMetadata> assertingPartyMetadataRowMapper = new AssertingPartyMetadataRowMapper(
57-
ResultSet::getBytes);
54+
private final RowMapper<AssertingPartyMetadata> assertingPartyMetadataRowMapper = new AssertingPartyMetadataRowMapper();
5855

5956
private final AssertingPartyMetadataParametersMapper assertingPartyMetadataParametersMapper = new AssertingPartyMetadataParametersMapper();
6057

6158
// @formatter:off
62-
static final String COLUMN_NAMES = "entity_id, "
63-
+ "singlesignon_url, "
64-
+ "singlesignon_binding, "
65-
+ "singlesignon_sign_request, "
66-
+ "signing_algorithms, "
67-
+ "verification_credentials, "
68-
+ "encryption_credentials, "
69-
+ "singlelogout_url, "
70-
+ "singlelogout_response_url, "
71-
+ "singlelogout_binding";
59+
static final String[] COLUMN_NAMES = { "entity_id",
60+
"single_sign_on_service_location",
61+
"single_sign_on_service_binding",
62+
"want_authn_requests_signed",
63+
"signing_algorithms",
64+
"verification_credentials",
65+
"encryption_credentials",
66+
"single_logout_service_location",
67+
"single_logout_service_response_location",
68+
"single_logout_service_binding" };
69+
7270
// @formatter:on
7371

7472
private static final String TABLE_NAME = "saml2_asserting_party_metadata";
7573

7674
private static final String ENTITY_ID_FILTER = "entity_id = ?";
7775

7876
// @formatter:off
79-
private static final String LOAD_BY_ID_SQL = "SELECT " + COLUMN_NAMES
77+
private static final String LOAD_BY_ID_SQL = "SELECT " + String.join(",", COLUMN_NAMES)
8078
+ " FROM " + TABLE_NAME
8179
+ " WHERE " + ENTITY_ID_FILTER;
8280

83-
private static final String LOAD_ALL_SQL = "SELECT " + COLUMN_NAMES
81+
private static final String LOAD_ALL_SQL = "SELECT " + String.join(",", COLUMN_NAMES)
8482
+ " FROM " + TABLE_NAME;
8583
// @formatter:on
8684

8785
// @formatter:off
8886
private static final String SAVE_CREDENTIAL_RECORD_SQL = "INSERT INTO " + TABLE_NAME
89-
+ " (" + COLUMN_NAMES + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
87+
+ " (" + String.join(",", COLUMN_NAMES) + ") VALUES (" + String.join(",", Collections.nCopies(COLUMN_NAMES.length, "?")) + ")";
9088
// @formatter:on
9189

9290
// @formatter:off
9391
private static final String UPDATE_CREDENTIAL_RECORD_SQL = "UPDATE " + TABLE_NAME
94-
+ " SET singlesignon_url = ?, "
95-
+ "singlesignon_binding = ?, "
96-
+ "singlesignon_sign_request = ?, "
97-
+ "signing_algorithms = ?, "
98-
+ "verification_credentials = ?, "
99-
+ "encryption_credentials = ?, "
100-
+ "singlelogout_url = ?, "
101-
+ "singlelogout_response_url = ?, "
102-
+ "singlelogout_binding = ?"
92+
+ " SET " + String.join(" = ?,", Arrays.copyOfRange(COLUMN_NAMES, 1, COLUMN_NAMES.length))
93+
+ " = ?"
10394
+ " WHERE " + ENTITY_ID_FILTER;
10495
// @formatter:on
10596

@@ -113,18 +104,6 @@ public JdbcAssertingPartyMetadataRepository(JdbcOperations jdbcOperations) {
113104
this.jdbcOperations = jdbcOperations;
114105
}
115106

116-
/**
117-
* Sets the {@link RowMapper} used for mapping the current row in
118-
* {@code java.sql.ResultSet} to {@link AssertingPartyMetadata}. The default is
119-
* {@link AssertingPartyMetadataRowMapper}.
120-
* @param assertingPartyMetadataRowMapper the {@link RowMapper} used for mapping the
121-
* current row in {@code java.sql.ResultSet} to {@link AssertingPartyMetadata}
122-
*/
123-
public void setAssertingPartyMetadataRowMapper(RowMapper<AssertingPartyMetadata> assertingPartyMetadataRowMapper) {
124-
Assert.notNull(assertingPartyMetadataRowMapper, "assertingPartyMetadataRowMapper cannot be null");
125-
this.assertingPartyMetadataRowMapper = assertingPartyMetadataRowMapper;
126-
}
127-
128107
@Override
129108
public AssertingPartyMetadata findByEntityId(String entityId) {
130109
Assert.hasText(entityId, "entityId cannot be empty");
@@ -172,60 +151,37 @@ private int updateCredentialRecord(AssertingPartyMetadata metadata) {
172151
*/
173152
private static final class AssertingPartyMetadataRowMapper implements RowMapper<AssertingPartyMetadata> {
174153

175-
private final Log logger = LogFactory.getLog(AssertingPartyMetadataRowMapper.class);
176-
177154
private final Deserializer<Object> deserializer = new DefaultDeserializer();
178155

179-
private final GetBytes getBytes;
180-
181-
AssertingPartyMetadataRowMapper(GetBytes getBytes) {
182-
this.getBytes = getBytes;
183-
}
184-
185156
@Override
186157
public AssertingPartyMetadata mapRow(ResultSet rs, int rowNum) throws SQLException {
187-
String entityId = rs.getString("entity_id");
188-
String singleSignOnUrl = rs.getString("singlesignon_url");
189-
Saml2MessageBinding singleSignOnBinding = Saml2MessageBinding.from(rs.getString("singlesignon_binding"));
190-
boolean singleSignOnSignRequest = rs.getBoolean("singlesignon_sign_request");
191-
String singleLogoutUrl = rs.getString("singlelogout_url");
192-
String singleLogoutResponseUrl = rs.getString("singlelogout_response_url");
193-
Saml2MessageBinding singleLogoutBinding = Saml2MessageBinding.from(rs.getString("singlelogout_binding"));
194-
byte[] signingAlgorithmsBytes = this.getBytes.getBytes(rs, "signing_algorithms");
195-
byte[] verificationCredentialsBytes = this.getBytes.getBytes(rs, "verification_credentials");
196-
byte[] encryptionCredentialsBytes = this.getBytes.getBytes(rs, "encryption_credentials");
197-
158+
String entityId = rs.getString(COLUMN_NAMES[0]);
159+
String singleSignOnUrl = rs.getString(COLUMN_NAMES[1]);
160+
Saml2MessageBinding singleSignOnBinding = Saml2MessageBinding.from(rs.getString(COLUMN_NAMES[2]));
161+
boolean singleSignOnSignRequest = rs.getBoolean(COLUMN_NAMES[3]);
162+
List<String> algorithms = List.of(rs.getString(COLUMN_NAMES[4]).split(","));
163+
byte[] verificationCredentialsBytes = rs.getBytes(COLUMN_NAMES[5]);
164+
byte[] encryptionCredentialsBytes = rs.getBytes(COLUMN_NAMES[6]);
165+
ThrowingFunction<byte[], Collection<Saml2X509Credential>> credentials = (
166+
bytes) -> (Collection<Saml2X509Credential>) this.deserializer.deserializeFromByteArray(bytes);
198167
AssertingPartyMetadata.Builder<?> builder = new AssertingPartyDetails.Builder();
199-
try {
200-
if (signingAlgorithmsBytes != null) {
201-
List<String> signingAlgorithms = (List<String>) this.deserializer
202-
.deserializeFromByteArray(signingAlgorithmsBytes);
203-
builder.signingAlgorithms((algorithms) -> algorithms.addAll(signingAlgorithms));
204-
}
205-
if (verificationCredentialsBytes != null) {
206-
Collection<Saml2X509Credential> verificationCredentials = (Collection<Saml2X509Credential>) this.deserializer
207-
.deserializeFromByteArray(verificationCredentialsBytes);
208-
builder.verificationX509Credentials((credentials) -> credentials.addAll(verificationCredentials));
209-
}
210-
if (encryptionCredentialsBytes != null) {
211-
Collection<Saml2X509Credential> encryptionCredentials = (Collection<Saml2X509Credential>) this.deserializer
212-
.deserializeFromByteArray(encryptionCredentialsBytes);
213-
builder.encryptionX509Credentials((credentials) -> credentials.addAll(encryptionCredentials));
214-
}
215-
}
216-
catch (Exception ex) {
217-
this.logger.debug(LogMessage.format("Parsing serialized credentials for entity %s failed", entityId),
218-
ex);
219-
return null;
220-
}
168+
Collection<Saml2X509Credential> verificationCredentials = credentials.apply(verificationCredentialsBytes);
169+
Collection<Saml2X509Credential> encryptionCredentials = (encryptionCredentialsBytes != null)
170+
? credentials.apply(encryptionCredentialsBytes) : List.of();
171+
String singleLogoutUrl = rs.getString(COLUMN_NAMES[7]);
172+
String singleLogoutResponseUrl = rs.getString(COLUMN_NAMES[8]);
173+
Saml2MessageBinding singleLogoutBinding = Saml2MessageBinding.from(rs.getString(COLUMN_NAMES[9]));
221174

222175
builder.entityId(entityId)
223176
.wantAuthnRequestsSigned(singleSignOnSignRequest)
224177
.singleSignOnServiceLocation(singleSignOnUrl)
225178
.singleSignOnServiceBinding(singleSignOnBinding)
226179
.singleLogoutServiceLocation(singleLogoutUrl)
227180
.singleLogoutServiceBinding(singleLogoutBinding)
228-
.singleLogoutServiceResponseLocation(singleLogoutResponseUrl);
181+
.singleLogoutServiceResponseLocation(singleLogoutResponseUrl)
182+
.signingAlgorithms((a) -> a.addAll(algorithms))
183+
.verificationX509Credentials((c) -> c.addAll(verificationCredentials))
184+
.encryptionX509Credentials((c) -> c.addAll(encryptionCredentials));
229185
return builder.build();
230186
}
231187

@@ -244,8 +200,7 @@ public List<SqlParameterValue> apply(AssertingPartyMetadata record) {
244200
parameters.add(new SqlParameterValue(Types.VARCHAR, record.getSingleSignOnServiceLocation()));
245201
parameters.add(new SqlParameterValue(Types.VARCHAR, record.getSingleSignOnServiceBinding().getUrn()));
246202
parameters.add(new SqlParameterValue(Types.BOOLEAN, record.getWantAuthnRequestsSigned()));
247-
ThrowingFunction<List<String>, byte[]> algorithms = this.serializer::serializeToByteArray;
248-
parameters.add(new SqlParameterValue(Types.BLOB, algorithms.apply(record.getSigningAlgorithms())));
203+
parameters.add(new SqlParameterValue(Types.BLOB, String.join(",", record.getSigningAlgorithms())));
249204
ThrowingFunction<Collection<Saml2X509Credential>, byte[]> credentials = this.serializer::serializeToByteArray;
250205
parameters
251206
.add(new SqlParameterValue(Types.BLOB, credentials.apply(record.getVerificationX509Credentials())));
@@ -259,10 +214,4 @@ public List<SqlParameterValue> apply(AssertingPartyMetadata record) {
259214

260215
}
261216

262-
private interface GetBytes {
263-
264-
byte[] getBytes(ResultSet rs, String columnName) throws SQLException;
265-
266-
}
267-
268217
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
CREATE TABLE saml2_asserting_party_metadata
22
(
3-
entity_id VARCHAR(1000) NOT NULL,
4-
singlesignon_url VARCHAR(1000) NOT NULL,
5-
singlesignon_binding VARCHAR(100),
6-
singlesignon_sign_request boolean,
7-
signing_algorithms BYTEA,
8-
verification_credentials BYTEA NOT NULL,
9-
encryption_credentials BYTEA,
10-
singlelogout_url VARCHAR(1000),
11-
singlelogout_response_url VARCHAR(1000),
12-
singlelogout_binding VARCHAR(100),
3+
entity_id VARCHAR(1000) NOT NULL,
4+
single_sign_on_service_location VARCHAR(1000) NOT NULL,
5+
single_sign_on_service_binding VARCHAR(100),
6+
want_authn_requests_signed boolean,
7+
signing_algorithms BYTEA,
8+
verification_credentials BYTEA NOT NULL,
9+
encryption_credentials BYTEA,
10+
single_logout_service_location VARCHAR(1000),
11+
single_logout_service_response_location VARCHAR(1000),
12+
single_logout_service_binding VARCHAR(100),
1313
PRIMARY KEY (entity_id)
1414
);
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
CREATE TABLE saml2_asserting_party_metadata
22
(
3-
entity_id VARCHAR(1000) NOT NULL,
4-
singlesignon_url VARCHAR(1000) NOT NULL,
5-
singlesignon_binding VARCHAR(100),
6-
singlesignon_sign_request boolean,
7-
signing_algorithms blob,
8-
verification_credentials blob NOT NULL,
9-
encryption_credentials blob,
10-
singlelogout_url VARCHAR(1000),
11-
singlelogout_response_url VARCHAR(1000),
12-
singlelogout_binding VARCHAR(100),
3+
entity_id VARCHAR(1000) NOT NULL,
4+
single_sign_on_service_location VARCHAR(1000) NOT NULL,
5+
single_sign_on_service_binding VARCHAR(100),
6+
want_authn_requests_signed boolean,
7+
signing_algorithms VARCHAR(256) NOT NULL,
8+
verification_credentials blob NOT NULL,
9+
encryption_credentials blob,
10+
single_logout_service_location VARCHAR(1000),
11+
single_logout_service_response_location VARCHAR(1000),
12+
single_logout_service_binding VARCHAR(100),
1313
PRIMARY KEY (entity_id)
1414
);

saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/JdbcAssertingPartyMetadataRepositoryTests.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void findByEntityIdWhenEntityIdIsNullThenThrowIllegalArgumentException() {
7979
}
8080

8181
@Test
82-
void findByEntityId() {
82+
void findByEntityIdWhenEntityPresentThenReturns() {
8383
this.repository.save(this.metadata);
8484

8585
AssertingPartyMetadata found = this.repository.findByEntityId(this.metadata.getEntityId());
@@ -88,17 +88,14 @@ void findByEntityId() {
8888
}
8989

9090
@Test
91-
void findByEntityIdWhenNotExists() {
91+
void findByEntityIdWhenNotExistsThenNull() {
9292
AssertingPartyMetadata found = this.repository.findByEntityId("non-existent-entity-id");
9393
assertThat(found).isNull();
9494
}
9595

9696
@Test
97-
void iterator() {
98-
AssertingPartyMetadata second = RelyingPartyRegistration.withAssertingPartyMetadata(this.metadata)
99-
.assertingPartyMetadata((a) -> a.entityId("https://example.org/idp"))
100-
.build()
101-
.getAssertingPartyMetadata();
97+
void iteratorWhenEnitiesExistThenContains() {
98+
AssertingPartyMetadata second = this.metadata.mutate().entityId("https://example.org/idp").build();
10299
this.repository.save(this.metadata);
103100
this.repository.save(second);
104101

0 commit comments

Comments
 (0)