From b25fde4ff3c31040e22f76818775c3f5699402dd Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 24 Jul 2015 07:44:56 +0200 Subject: [PATCH] DATAMONGO-1260 - Prevent accidental authentication misconfiguration on SimpleMongoDbFactory. We now reject configuration using MongoClient along with UserCredentials in SimpleMongoDbFactory. This move favors the native authentication mechanism provided via MongoCredential. Original pull request: #309. --- .../mongodb/core/SimpleMongoDbFactory.java | 10 ++++- .../core/SimpleMongoDbFactoryUnitTests.java | 44 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java index 7916c2525..572dea038 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java @@ -19,6 +19,7 @@ import java.net.UnknownHostException; import org.springframework.beans.factory.DisposableBean; import org.springframework.dao.DataAccessException; +import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.authentication.UserCredentials; import org.springframework.data.mongodb.MongoDbFactory; @@ -103,8 +104,8 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory { */ @Deprecated public SimpleMongoDbFactory(MongoURI uri) throws MongoException, UnknownHostException { - this(new Mongo(uri), uri.getDatabase(), new UserCredentials(uri.getUsername(), parseChars(uri.getPassword())), - true, uri.getDatabase()); + this(new Mongo(uri), uri.getDatabase(), new UserCredentials(uri.getUsername(), parseChars(uri.getPassword())), true, + uri.getDatabase()); } /** @@ -132,6 +133,11 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory { private SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials, boolean mongoInstanceCreated, String authenticationDatabaseName) { + if (mongo instanceof MongoClient && (credentials != null && !UserCredentials.NO_CREDENTIALS.equals(credentials))) { + throw new InvalidDataAccessApiUsageException( + "Usage of 'UserCredentials' with 'MongoClient' is no longer supported. Please use 'MongoCredential' for 'MongoClient' or just 'Mongo'."); + } + Assert.notNull(mongo, "Mongo must not be null"); Assert.hasText(databaseName, "Database name must not be empty"); Assert.isTrue(databaseName.matches("[\\w-]+"), diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java index de2ec283c..9967de75e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java @@ -22,10 +22,13 @@ import static org.springframework.test.util.ReflectionTestUtils.*; import java.net.UnknownHostException; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.authentication.UserCredentials; import org.springframework.data.mongodb.MongoDbFactory; @@ -43,6 +46,7 @@ import com.mongodb.MongoURI; @RunWith(MockitoJUnitRunner.class) public class SimpleMongoDbFactoryUnitTests { + public @Rule ExpectedException expectedException = ExpectedException.none(); @Mock Mongo mongo; /** @@ -115,6 +119,46 @@ public class SimpleMongoDbFactoryUnitTests { assertThat(getField(factory, "authenticationDatabaseName").toString(), is("FooBar")); } + /** + * @see DATAMONGO-1260 + */ + @Test + public void rejectsMongoClientWithUserCredentials() { + + expectedException.expect(InvalidDataAccessApiUsageException.class); + expectedException.expectMessage("use 'MongoCredential' for 'MongoClient'"); + + new SimpleMongoDbFactory(mock(MongoClient.class), "cairhienin", new UserCredentials("moiraine", "sedai")); + } + + /** + * @see DATAMONGO-1260 + */ + @Test + public void rejectsMongoClientWithUserCredentialsAndAuthDb() { + + expectedException.expect(InvalidDataAccessApiUsageException.class); + expectedException.expectMessage("use 'MongoCredential' for 'MongoClient'"); + + new SimpleMongoDbFactory(mock(MongoClient.class), "malkieri", new UserCredentials("lan", "mandragoran"), "authdb"); + } + + /** + * @see DATAMONGO-1260 + */ + @Test + public void shouldNotRejectMongoClientWithNoCredentials() { + new SimpleMongoDbFactory(mock(MongoClient.class), "andoran", UserCredentials.NO_CREDENTIALS); + } + + /** + * @see DATAMONGO-1260 + */ + @Test + public void shouldNotRejectMongoClientWithEmptyUserCredentials() { + new SimpleMongoDbFactory(mock(MongoClient.class), "shangtai", new UserCredentials("", "")); + } + @SuppressWarnings("deprecation") private void rejectsDatabaseName(String databaseName) {