15
15
*/
16
16
package org .springframework .security .oauth2 .server .authorization .client ;
17
17
18
+ import java .nio .charset .StandardCharsets ;
19
+ import java .sql .PreparedStatement ;
20
+ import java .sql .ResultSet ;
21
+ import java .sql .SQLException ;
22
+ import java .sql .Timestamp ;
23
+ import java .sql .Types ;
24
+ import java .time .Duration ;
25
+ import java .time .Instant ;
26
+ import java .util .ArrayList ;
27
+ import java .util .Arrays ;
28
+ import java .util .Collections ;
29
+ import java .util .HashMap ;
30
+ import java .util .List ;
31
+ import java .util .Map ;
32
+ import java .util .Set ;
33
+ import java .util .function .Function ;
34
+
18
35
import com .fasterxml .jackson .core .JsonProcessingException ;
19
36
import com .fasterxml .jackson .databind .ObjectMapper ;
20
- import org .springframework .jdbc .core .*;
37
+
38
+ import org .springframework .jdbc .core .ArgumentPreparedStatementSetter ;
39
+ import org .springframework .jdbc .core .JdbcOperations ;
40
+ import org .springframework .jdbc .core .PreparedStatementSetter ;
41
+ import org .springframework .jdbc .core .RowMapper ;
42
+ import org .springframework .jdbc .core .SqlParameterValue ;
21
43
import org .springframework .jdbc .support .lob .DefaultLobHandler ;
22
44
import org .springframework .jdbc .support .lob .LobCreator ;
23
45
import org .springframework .jdbc .support .lob .LobHandler ;
26
48
import org .springframework .security .oauth2 .server .authorization .config .ClientSettings ;
27
49
import org .springframework .security .oauth2 .server .authorization .config .TokenSettings ;
28
50
import org .springframework .util .Assert ;
29
-
30
- import java .nio .charset .StandardCharsets ;
31
- import java .sql .*;
32
- import java .time .Duration ;
33
- import java .time .Instant ;
34
- import java .util .*;
35
- import java .util .function .Function ;
36
- import java .util .stream .Collectors ;
51
+ import org .springframework .util .StringUtils ;
37
52
38
53
/**
39
54
* JDBC-backed registered client repository
@@ -72,17 +87,44 @@ public class JdbcRegisteredClientRepository implements RegisteredClientRepositor
72
87
73
88
private final JdbcOperations jdbcOperations ;
74
89
75
- private final LobHandler lobHandler = new DefaultLobHandler () ;
90
+ private final LobHandler lobHandler ;
76
91
77
- private final ObjectMapper objectMapper ;
92
+ /**
93
+ * Constructs a {@code JdbcRegisteredClientRepository} using the provided parameters.
94
+ *
95
+ * @param jdbcOperations the JDBC operations
96
+ */
97
+ public JdbcRegisteredClientRepository (JdbcOperations jdbcOperations ) {
98
+ this (jdbcOperations , new ObjectMapper ());
99
+ }
78
100
101
+ /**
102
+ * Constructs a {@code JdbcRegisteredClientRepository} using the provided parameters.
103
+ *
104
+ * @param jdbcOperations the JDBC operations
105
+ * @param objectMapper the object mapper
106
+ */
79
107
public JdbcRegisteredClientRepository (JdbcOperations jdbcOperations , ObjectMapper objectMapper ) {
108
+ this (jdbcOperations , new DefaultLobHandler (), objectMapper );
109
+ }
110
+
111
+ /**
112
+ * Constructs a {@code JdbcRegisteredClientRepository} using the provided parameters.
113
+ *
114
+ * @param jdbcOperations the JDBC operations
115
+ * @param lobHandler the handler for large binary fields and large text fields
116
+ * @param objectMapper the object mapper
117
+ */
118
+ public JdbcRegisteredClientRepository (JdbcOperations jdbcOperations , LobHandler lobHandler , ObjectMapper objectMapper ) {
80
119
Assert .notNull (jdbcOperations , "jdbcOperations cannot be null" );
120
+ Assert .notNull (lobHandler , "lobHandler cannot be null" );
81
121
Assert .notNull (objectMapper , "objectMapper cannot be null" );
82
122
this .jdbcOperations = jdbcOperations ;
83
- this .objectMapper = objectMapper ;
84
- this .registeredClientRowMapper = new DefaultRegisteredClientRowMapper ();
85
- this .registeredClientParametersMapper = new DefaultRegisteredClientParametersMapper ();
123
+ this .lobHandler = lobHandler ;
124
+ DefaultRegisteredClientRowMapper registeredClientRowMapper = new DefaultRegisteredClientRowMapper (objectMapper );
125
+ registeredClientRowMapper .setLobHandler (lobHandler );
126
+ this .registeredClientRowMapper = registeredClientRowMapper ;
127
+ this .registeredClientParametersMapper = new DefaultRegisteredClientParametersMapper (objectMapper );
86
128
}
87
129
88
130
/**
@@ -148,23 +190,27 @@ private RegisteredClient findBy(String condStr, Object...args) {
148
190
return !lst .isEmpty () ? lst .get (0 ) : null ;
149
191
}
150
192
151
- private class DefaultRegisteredClientRowMapper implements RowMapper <RegisteredClient > {
193
+ public static class DefaultRegisteredClientRowMapper implements RowMapper <RegisteredClient > {
194
+
195
+ private final ObjectMapper objectMapper ;
152
196
153
- private final LobHandler lobHandler = new DefaultLobHandler ();
197
+ private LobHandler lobHandler = new DefaultLobHandler ();
154
198
155
- private Collection <String > parseList (String s ) {
156
- return s != null ? Arrays .asList (s .split ("\\ |" )) : Collections .emptyList ();
199
+ public DefaultRegisteredClientRowMapper (ObjectMapper objectMapper ) {
200
+ this .objectMapper = objectMapper ;
201
+ }
202
+
203
+ private Set <String > parseList (String s ) {
204
+ return s != null ? StringUtils .commaDelimitedListToSet (s ) : Collections .emptySet ();
157
205
}
158
206
159
207
@ Override
160
208
@ SuppressWarnings ("unchecked" )
161
209
public RegisteredClient mapRow (ResultSet rs , int rowNum ) throws SQLException {
162
- Collection <String > scopes = parseList (rs .getString ("scopes" ));
163
- List <AuthorizationGrantType > authGrantTypes = parseList (rs .getString ("authorization_grant_types" ))
164
- .stream ().map (AUTHORIZATION_GRANT_TYPE_MAP ::get ).collect (Collectors .toList ());
165
- List <ClientAuthenticationMethod > clientAuthMethods = parseList (rs .getString ("client_authentication_methods" ))
166
- .stream ().map (CLIENT_AUTHENTICATION_METHOD_MAP ::get ).collect (Collectors .toList ());
167
- Collection <String > redirectUris = parseList (rs .getString ("redirect_uris" ));
210
+ Set <String > scopes = parseList (rs .getString ("scopes" ));
211
+ Set <String > authGrantTypes = parseList (rs .getString ("authorization_grant_types" ));
212
+ Set <String > clientAuthMethods = parseList (rs .getString ("client_authentication_methods" ));
213
+ Set <String > redirectUris = parseList (rs .getString ("redirect_uris" ));
168
214
Timestamp clientIssuedAt = rs .getTimestamp ("client_id_issued_at" );
169
215
Timestamp clientSecretExpiresAt = rs .getTimestamp ("client_secret_expires_at" );
170
216
byte [] clientSecretBytes = this .lobHandler .getBlobAsBytes (rs , "client_secret" );
@@ -176,8 +222,10 @@ public RegisteredClient mapRow(ResultSet rs, int rowNum) throws SQLException {
176
222
.clientSecret (clientSecret )
177
223
.clientSecretExpiresAt (clientSecretExpiresAt != null ? clientSecretExpiresAt .toInstant () : null )
178
224
.clientName (rs .getString ("client_name" ))
179
- .clientAuthenticationMethods (coll -> coll .addAll (clientAuthMethods ))
180
- .authorizationGrantTypes (coll -> coll .addAll (authGrantTypes ))
225
+ .authorizationGrantTypes (coll -> authGrantTypes .forEach (authGrantType ->
226
+ coll .add (AUTHORIZATION_GRANT_TYPE_MAP .get (authGrantType ))))
227
+ .clientAuthenticationMethods (coll -> clientAuthMethods .forEach (clientAuthMethod ->
228
+ coll .add (CLIENT_AUTHENTICATION_METHOD_MAP .get (clientAuthMethod ))))
181
229
.redirectUris (coll -> coll .addAll (redirectUris ))
182
230
.scopes (coll -> coll .addAll (scopes ));
183
231
@@ -189,8 +237,7 @@ public RegisteredClient mapRow(ResultSet rs, int rowNum) throws SQLException {
189
237
try {
190
238
String tokenSettingsJson = rs .getString ("token_settings" );
191
239
if (tokenSettingsJson != null ) {
192
-
193
- Map <String , Object > m = JdbcRegisteredClientRepository .this .objectMapper .readValue (tokenSettingsJson , Map .class );
240
+ Map <String , Object > m = this .objectMapper .readValue (tokenSettingsJson , Map .class );
194
241
195
242
Number accessTokenTTL = (Number ) m .get ("access_token_ttl" );
196
243
if (accessTokenTTL != null ) {
@@ -210,8 +257,7 @@ public RegisteredClient mapRow(ResultSet rs, int rowNum) throws SQLException {
210
257
211
258
String clientSettingsJson = rs .getString ("client_settings" );
212
259
if (clientSettingsJson != null ) {
213
-
214
- Map <String , Object > m = JdbcRegisteredClientRepository .this .objectMapper .readValue (clientSettingsJson , Map .class );
260
+ Map <String , Object > m = this .objectMapper .readValue (clientSettingsJson , Map .class );
215
261
216
262
Boolean requireProofKey = (Boolean ) m .get ("require_proof_key" );
217
263
if (requireProofKey != null ) {
@@ -223,17 +269,28 @@ public RegisteredClient mapRow(ResultSet rs, int rowNum) throws SQLException {
223
269
cs .requireUserConsent (requireUserConsent );
224
270
}
225
271
}
226
-
227
-
228
272
} catch (JsonProcessingException e ) {
229
273
throw new IllegalArgumentException (e .getMessage (), e );
230
274
}
231
275
232
276
return rc ;
233
277
}
278
+
279
+ public final void setLobHandler (LobHandler lobHandler ) {
280
+ Assert .notNull (lobHandler , "lobHandler cannot be null" );
281
+ this .lobHandler = lobHandler ;
282
+ }
283
+
234
284
}
235
285
236
- private class DefaultRegisteredClientParametersMapper implements Function <RegisteredClient , List <SqlParameterValue >> {
286
+ public static class DefaultRegisteredClientParametersMapper implements Function <RegisteredClient , List <SqlParameterValue >> {
287
+
288
+ private final ObjectMapper objectMapper ;
289
+
290
+ private DefaultRegisteredClientParametersMapper (ObjectMapper objectMapper ) {
291
+ this .objectMapper = objectMapper ;
292
+ }
293
+
237
294
@ Override
238
295
public List <SqlParameterValue > apply (RegisteredClient registeredClient ) {
239
296
try {
@@ -256,13 +313,13 @@ public List<SqlParameterValue> apply(RegisteredClient registeredClient) {
256
313
Map <String , Object > clientSettings = new HashMap <>();
257
314
clientSettings .put ("require_proof_key" , registeredClient .getClientSettings ().requireProofKey ());
258
315
clientSettings .put ("require_user_consent" , registeredClient .getClientSettings ().requireUserConsent ());
259
- String clientSettingsJson = JdbcRegisteredClientRepository . this .objectMapper .writeValueAsString (clientSettings );
316
+ String clientSettingsJson = this .objectMapper .writeValueAsString (clientSettings );
260
317
261
318
Map <String , Object > tokenSettings = new HashMap <>();
262
319
tokenSettings .put ("access_token_ttl" , registeredClient .getTokenSettings ().accessTokenTimeToLive ().toMillis ());
263
320
tokenSettings .put ("reuse_refresh_tokens" , registeredClient .getTokenSettings ().reuseRefreshTokens ());
264
321
tokenSettings .put ("refresh_token_ttl" , registeredClient .getTokenSettings ().refreshTokenTimeToLive ().toMillis ());
265
- String tokenSettingsJson = JdbcRegisteredClientRepository . this .objectMapper .writeValueAsString (tokenSettings );
322
+ String tokenSettingsJson = this .objectMapper .writeValueAsString (tokenSettings );
266
323
267
324
return Arrays .asList (
268
325
new SqlParameterValue (Types .VARCHAR , registeredClient .getId ()),
@@ -271,16 +328,17 @@ public List<SqlParameterValue> apply(RegisteredClient registeredClient) {
271
328
new SqlParameterValue (Types .BLOB , registeredClient .getClientSecret ().getBytes (StandardCharsets .UTF_8 )),
272
329
new SqlParameterValue (Types .TIMESTAMP , clientSecretExpiresAt ),
273
330
new SqlParameterValue (Types .VARCHAR , registeredClient .getClientName ()),
274
- new SqlParameterValue (Types .VARCHAR , String . join ( "|" , clientAuthenticationMethodNames )),
275
- new SqlParameterValue (Types .VARCHAR , String . join ( "|" , authorizationGrantTypeNames )),
276
- new SqlParameterValue (Types .VARCHAR , String . join ( "|" , registeredClient .getRedirectUris ())),
277
- new SqlParameterValue (Types .VARCHAR , String . join ( "|" , registeredClient .getScopes ())),
331
+ new SqlParameterValue (Types .VARCHAR , StringUtils . collectionToCommaDelimitedString ( clientAuthenticationMethodNames )),
332
+ new SqlParameterValue (Types .VARCHAR , StringUtils . collectionToCommaDelimitedString ( authorizationGrantTypeNames )),
333
+ new SqlParameterValue (Types .VARCHAR , StringUtils . collectionToCommaDelimitedString ( registeredClient .getRedirectUris ())),
334
+ new SqlParameterValue (Types .VARCHAR , StringUtils . collectionToCommaDelimitedString ( registeredClient .getScopes ())),
278
335
new SqlParameterValue (Types .VARCHAR , clientSettingsJson ),
279
336
new SqlParameterValue (Types .VARCHAR , tokenSettingsJson ));
280
337
} catch (JsonProcessingException e ) {
281
338
throw new IllegalArgumentException (e .getMessage (), e );
282
339
}
283
340
}
341
+
284
342
}
285
343
286
344
private static final class LobCreatorArgumentPreparedStatementSetter extends ArgumentPreparedStatementSetter {
0 commit comments