From 5f32339175ce63963295a8201f6fa935a69bfb8e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 13 Aug 2018 09:29:21 +0200 Subject: [PATCH] DATAMONGO-2051 - Add support for SCRAM-SHA-256 authentication mechanism to MongoCredentialPropertyEditor. Original pull request: #597. Related pull request: #598. --- .../config/MongoCredentialPropertyEditor.java | 16 ++++++++++++++++ .../data/mongodb/util/MongoClientVersion.java | 15 +++++++++++++-- ...MongoCredentialPropertyEditorUnitTests.java | 18 ++++++++++++++++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java index bc8a76ae2..ea28e479a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java @@ -16,6 +16,7 @@ package org.springframework.data.mongodb.config; import java.beans.PropertyEditorSupport; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -23,6 +24,7 @@ import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import com.mongodb.MongoCredential; @@ -97,6 +99,20 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport { verifyDatabasePresent(database); credentials.add(MongoCredential.createScramSha1Credential(userNameAndPassword[0], database, userNameAndPassword[1].toCharArray())); + } else if ("SCRAM-SHA-256".equals(authMechanism)) { + + Method createScramSha256Credential = ReflectionUtils.findMethod(MongoCredential.class, + "createScramSha256Credential"); + + if (createScramSha256Credential == null) { + throw new IllegalArgumentException( + "SCRAM-SHA-256 auth mechanism is available as of MongoDB 4 and MongoDB Java Driver 3.8! Please make sure to use at least those versions."); + } + + verifyUsernameAndPasswordPresent(userNameAndPassword); + verifyDatabasePresent(database); + credentials.add(MongoCredential.class.cast(ReflectionUtils.invokeMethod(createScramSha256Credential, null, + userNameAndPassword[0], database, userNameAndPassword[1].toCharArray()))); } else { throw new IllegalArgumentException( String.format("Cannot create MongoCredentials for unknown auth mechanism '%s'!", authMechanism)); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java index 272f885a7..f672ffb8a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java @@ -20,7 +20,7 @@ import org.springframework.util.ClassUtils; /** * {@link MongoClientVersion} holds information about the used mongo-java client and is used to distinguish between * different versions. - * + * * @author Christoph Strobl * @since 1.7 */ @@ -32,6 +32,9 @@ public class MongoClientVersion { private static final boolean IS_MONGO_34 = ClassUtils.isPresent("org.bson.types.Decimal128", MongoClientVersion.class.getClassLoader()); + private static final boolean IS_MONGO_38 = ClassUtils.isPresent("com.mongodb.TransactionOptions", + MongoClientVersion.class.getClassLoader()); + private static final boolean IS_ASYNC_CLIENT = ClassUtils.isPresent("com.mongodb.async.client.MongoClient", MongoClientVersion.class.getClassLoader()); @@ -51,9 +54,17 @@ public class MongoClientVersion { } /** - * @return {lliteral true} if MongoDB Java driver is on classpath. + * @return {@literal true} if MongoDB Java driver is on classpath. */ public static boolean isAsyncClient() { return IS_ASYNC_CLIENT; } + + /** + * @return {@literal true} if MongoDB Java driver version 3.8 or later is on classpath. + * @since 1.10.15 + */ + public static boolean isMongo38Driver() { + return IS_MONGO_38; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java index f0a9073b5..c20e4af90 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java @@ -15,15 +15,16 @@ */ package org.springframework.data.mongodb.config; -import static org.hamcrest.collection.IsIterableContainingInOrder.*; -import static org.hamcrest.core.IsNull.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.junit.Assume.*; import java.util.Arrays; import java.util.List; import org.junit.Before; import org.junit.Test; +import org.springframework.data.mongodb.util.MongoClientVersion; import org.springframework.util.StringUtils; import com.mongodb.MongoCredential; @@ -65,6 +66,9 @@ public class MongoCredentialPropertyEditorUnitTests { static final String USER_5_AUTH_STRING_WITH_PLAIN_AUTH_MECHANISM = USER_5_AUTH_STRING + "?uri.authMechanism=PLAIN"; static final String USER_5_AUTH_STRING_WITH_QUERY_ARGS = USER_5_AUTH_STRING + "?uri.authMechanism=PLAIN&foo=&bar"; + static final String SCRAM_SHA_256_AUTH_STRING = USER_1_NAME + ":" + USER_1_PWD + "@" + USER_1_DB + + "?uri.authMechanism=SCRAM-SHA-256"; + static final MongoCredential USER_1_CREDENTIALS = MongoCredential.createCredential(USER_1_NAME, USER_1_DB, USER_1_PWD.toCharArray()); static final MongoCredential USER_1_CREDENTIALS_PLAIN_AUTH = MongoCredential.createPlainCredential(USER_1_NAME, @@ -236,6 +240,16 @@ public class MongoCredentialPropertyEditorUnitTests { assertThat((List) editor.getValue(), contains(USER_5_CREDENTIALS_PLAIN_AUTH)); } + @Test // DATAMONGO-2051 + public void shouldReturnScramSha256Credentials() { + + assumeTrue(MongoClientVersion.isMongo38Driver()); + + editor.setAsText(SCRAM_SHA_256_AUTH_STRING); + + assertThat((List) editor.getValue(), is(not(empty()))); + } + @Test(expected = IllegalArgumentException.class) // DATAMONGO-2016 @SuppressWarnings("unchecked") public void failsGracefullyOnEmptyQueryArgument() {