Browse Source

DATAMONGO-1257 - <mongo:mongo-client /> element now supports usernames with a comma.

We now allow grouping credentials by enclosing them in single quotes like this:

credentials='CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry?uri.authMechanism=MONGODB-X509'

We also changed the required argument checks to be more authentication mechanism specific which means the pattern is now username[:password@database][?options].

Original pull request: #310.
pull/311/head
Christoph Strobl 11 years ago committed by Oliver Gierke
parent
commit
bebd0fa0e6
  1. 82
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java
  2. 79
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java

82
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java

@ -17,8 +17,11 @@ package org.springframework.data.mongodb.config; @@ -17,8 +17,11 @@ package org.springframework.data.mongodb.config;
import java.beans.PropertyEditorSupport;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.util.StringUtils;
@ -32,6 +35,8 @@ import com.mongodb.MongoCredential; @@ -32,6 +35,8 @@ import com.mongodb.MongoCredential;
*/
public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
private static final Pattern GROUP_PATTERN = Pattern.compile("(\\\\?')(.*?)\\1");
private static final String AUTH_MECHANISM_KEY = "uri.authMechanism";
private static final String USERNAME_PASSWORD_DELIMINATOR = ":";
private static final String DATABASE_DELIMINATOR = "@";
@ -51,11 +56,7 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport { @@ -51,11 +56,7 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
List<MongoCredential> credentials = new ArrayList<MongoCredential>();
for (String credentialString : text.split(",")) {
if (!text.contains(USERNAME_PASSWORD_DELIMINATOR) || !text.contains(DATABASE_DELIMINATOR)) {
throw new IllegalArgumentException("Credentials need to be in format 'username:password@database'!");
}
for (String credentialString : extractCredentialsString(text)) {
String[] userNameAndPassword = extractUserNameAndPassword(credentialString);
String database = extractDB(credentialString);
@ -68,16 +69,29 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport { @@ -68,16 +69,29 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
String authMechanism = options.getProperty(AUTH_MECHANISM_KEY);
if (MongoCredential.GSSAPI_MECHANISM.equals(authMechanism)) {
verifyUserNamePresent(userNameAndPassword);
credentials.add(MongoCredential.createGSSAPICredential(userNameAndPassword[0]));
} else if (MongoCredential.MONGODB_CR_MECHANISM.equals(authMechanism)) {
verifyUsernameAndPasswordPresent(userNameAndPassword);
verifyDatabasePresent(database);
credentials.add(MongoCredential.createMongoCRCredential(userNameAndPassword[0], database,
userNameAndPassword[1].toCharArray()));
} else if (MongoCredential.MONGODB_X509_MECHANISM.equals(authMechanism)) {
verifyUserNamePresent(userNameAndPassword);
credentials.add(MongoCredential.createMongoX509Credential(userNameAndPassword[0]));
} else if (MongoCredential.PLAIN_MECHANISM.equals(authMechanism)) {
verifyUsernameAndPasswordPresent(userNameAndPassword);
verifyDatabasePresent(database);
credentials.add(MongoCredential.createPlainCredential(userNameAndPassword[0], database,
userNameAndPassword[1].toCharArray()));
} else if (MongoCredential.SCRAM_SHA_1_MECHANISM.equals(authMechanism)) {
verifyUsernameAndPasswordPresent(userNameAndPassword);
verifyDatabasePresent(database);
credentials.add(MongoCredential.createScramSha1Credential(userNameAndPassword[0], database,
userNameAndPassword[1].toCharArray()));
} else {
@ -86,6 +100,9 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport { @@ -86,6 +100,9 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
}
}
} else {
verifyUsernameAndPasswordPresent(userNameAndPassword);
verifyDatabasePresent(database);
credentials.add(MongoCredential.createCredential(userNameAndPassword[0], database,
userNameAndPassword[1].toCharArray()));
}
@ -94,10 +111,34 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport { @@ -94,10 +111,34 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
setValue(credentials);
}
private List<String> extractCredentialsString(String source) {
Matcher matcher = GROUP_PATTERN.matcher(source);
List<String> list = new ArrayList<String>();
while (matcher.find()) {
String value = StringUtils.trimLeadingCharacter(matcher.group(), '\'');
list.add(StringUtils.trimTrailingCharacter(value, '\''));
}
if (!list.isEmpty()) {
return list;
}
return Arrays.asList(source.split(","));
}
private static String[] extractUserNameAndPassword(String text) {
int dbSeperationIndex = text.lastIndexOf(DATABASE_DELIMINATOR);
String userNameAndPassword = text.substring(0, dbSeperationIndex);
int index = text.lastIndexOf(DATABASE_DELIMINATOR);
if (index == -1) {
index = text.lastIndexOf(OPTIONS_DELIMINATOR);
}
if (index == -1) {
return new String[] {};
}
String userNameAndPassword = text.substring(0, index);
return userNameAndPassword.split(USERNAME_PASSWORD_DELIMINATOR);
}
@ -105,6 +146,10 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport { @@ -105,6 +146,10 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
int dbSeperationIndex = text.lastIndexOf(DATABASE_DELIMINATOR);
if (dbSeperationIndex == -1) {
return "";
}
String tmp = text.substring(dbSeperationIndex + 1);
int optionsSeperationIndex = tmp.lastIndexOf(OPTIONS_DELIMINATOR);
@ -129,4 +174,27 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport { @@ -129,4 +174,27 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
return properties;
}
private void verifyUserNamePresent(String[] source) {
if (source.length == 0 || !StringUtils.hasText(source[0])) {
throw new IllegalArgumentException("Credentials need to specify username!");
}
}
private void verifyUsernameAndPasswordPresent(String[] source) {
verifyUserNamePresent(source);
if (source.length != 2) {
throw new IllegalArgumentException(
"Credentials need to specify username and password like in 'username:password@database'!");
}
}
private void verifyDatabasePresent(String source) {
if (!StringUtils.hasText(source)) {
throw new IllegalArgumentException("Credentials need to specify database like in 'username:password@database'!");
}
}
}

79
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java

@ -43,6 +43,9 @@ public class MongoCredentialPropertyEditorUnitTests { @@ -43,6 +43,9 @@ public class MongoCredentialPropertyEditorUnitTests {
static final String USER_2_PWD = "warg";
static final String USER_2_DB = "snow";
static final String USER_3_NAME = "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry";
static final String USER_3_DB = "stark";
static final String USER_1_AUTH_STRING = USER_1_NAME + ":" + USER_1_PWD + "@" + USER_1_DB;
static final String USER_1_AUTH_STRING_WITH_PLAIN_AUTH_MECHANISM = USER_1_AUTH_STRING + "?uri.authMechanism=PLAIN";
@ -50,6 +53,9 @@ public class MongoCredentialPropertyEditorUnitTests { @@ -50,6 +53,9 @@ public class MongoCredentialPropertyEditorUnitTests {
static final String USER_2_AUTH_STRING_WITH_MONGODB_CR_AUTH_MECHANISM = USER_2_AUTH_STRING
+ "?uri.authMechanism=MONGODB-CR";
static final String USER_3_AUTH_STRING_WITH_X509_AUTH_MECHANISM = "'" + USER_3_NAME + "@" + USER_3_DB
+ "?uri.authMechanism=MONGODB-X509'";
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,
@ -60,6 +66,8 @@ public class MongoCredentialPropertyEditorUnitTests { @@ -60,6 +66,8 @@ public class MongoCredentialPropertyEditorUnitTests {
static final MongoCredential USER_2_CREDENTIALS_CR_AUTH = MongoCredential.createMongoCRCredential(USER_2_NAME,
USER_2_DB, USER_2_PWD.toCharArray());
static final MongoCredential USER_3_CREDENTIALS_X509_AUTH = MongoCredential.createMongoX509Credential(USER_3_NAME);
MongoCredentialPropertyEditor editor;
@Before
@ -168,4 +176,75 @@ public class MongoCredentialPropertyEditorUnitTests { @@ -168,4 +176,75 @@ public class MongoCredentialPropertyEditorUnitTests {
assertThat((List<MongoCredential>) editor.getValue(), contains(USER_1_CREDENTIALS_PLAIN_AUTH, USER_2_CREDENTIALS));
}
/**
* @see DATAMONGO-1257
*/
@Test
@SuppressWarnings("unchecked")
public void shouldReturnCredentialsValueCorrectlyWhenGivenMultipleQuotedUserNamePasswordStringWithDatabaseAndNoOptions() {
editor.setAsText(StringUtils.collectionToCommaDelimitedString(Arrays.asList("'" + USER_1_AUTH_STRING + "'", "'"
+ USER_2_AUTH_STRING + "'")));
assertThat((List<MongoCredential>) editor.getValue(), contains(USER_1_CREDENTIALS, USER_2_CREDENTIALS));
}
/**
* @see DATAMONGO-1257
*/
@Test
@SuppressWarnings("unchecked")
public void shouldReturnCredentialsValueCorrectlyWhenGivenSingleQuotedUserNamePasswordStringWithDatabaseAndNoOptions() {
editor.setAsText("'" + USER_1_AUTH_STRING + "'");
assertThat((List<MongoCredential>) editor.getValue(), contains(USER_1_CREDENTIALS));
}
/**
* @see DATAMONGO-1257
*/
@Test
@SuppressWarnings("unchecked")
public void shouldReturnX509CredentialsCorrectly() {
editor.setAsText(USER_3_AUTH_STRING_WITH_X509_AUTH_MECHANISM);
assertThat((List<MongoCredential>) editor.getValue(), contains(USER_3_CREDENTIALS_X509_AUTH));
}
/**
* @see DATAMONGO-1257
*/
@Test
@SuppressWarnings("unchecked")
public void shouldReturnX509CredentialsCorrectlyWhenNoDbSpecified() {
editor.setAsText("tyrion?uri.authMechanism=MONGODB-X509");
assertThat((List<MongoCredential>) editor.getValue(), contains(MongoCredential.createMongoX509Credential("tyrion")));
}
/**
* @see DATAMONGO-1257
*/
@Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionWhenNoDbSpecifiedForMongodbCR() {
editor.setAsText("tyrion?uri.authMechanism=MONGODB-CR");
editor.getValue();
}
/**
* @see DATAMONGO-1257
*/
@Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionWhenDbIsEmptyForMongodbCR() {
editor.setAsText("tyrion@?uri.authMechanism=MONGODB-CR");
editor.getValue();
}
}

Loading…
Cancel
Save