Spring数据mongodb,如何设置SSL?
Spring data mongodb, how to set SSL?
到目前为止,我还没有找到关于这个话题的好文章explanation/doc。
我正在使用
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.9.5.RELEASE</version>
</dependency>
我的代码如下所示:
@Bean
public MongoClientFactoryBean mongo() {
MongoClientFactoryBean mongo = new MongoClientFactoryBean();
mongo.setHost(host);
mongo.setPort(port);
mongo.setCredentials(new MongoCredential[]{MongoCredential.createCredential(username, database, password.toCharArray())});
return mongo;
}
@Bean
public MongoTemplate mongoTemplate(Mongo mongo) throws Exception {
return new MongoTemplate(mongo, database);
}
你知道我应该如何为此配置 SSL 吗?我可以允许无效证书吗?
等效的 mongo 命令行是
mongo --ssl --sslAllowInvalidCertificates --host <host> --port <port>
文档中有解释:请参考下面:
也可以使用以下配置来启用它
@Bean
public MongoClientOptions mongoClientOptions(){
System.setProperty ("javax.net.ssl.keyStore","<<PATH TO KEYSTOR >>");
System.setProperty ("javax.net.ssl.keyStorePassword","PASSWORD");
MongoClientOptions.Builder builder = MongoClientOptions.builder();
MongoClientOptions options=builder.sslEnabled(true).build();
return options;
}
将 mongo 客户端选项作为参数传递给 MongoClient 实例
public MongoClient(ServerAddress addr, MongoClientOptions options) {
super(addr, options);
}
进一步添加,当 mongo 进程以
启动时
mongo
--ssl --sslAllowInvalidCertificates --host --port
连接到 mongo 进程的客户端不必设置任何选项来支持它。
您还可以通过以下方式构建启用 ssl 的 mongo 实例。
public @Bean MongoClient mongoClient() throws Exception {
return new MongoClient(new MongoClientURI("mongodb://username:password@host:port/db?ssl=true"));
}
如果您使用 spring 引导,则可以通过以下方式在 application.properties 或 application.yml 中配置
spring.data.mongodb.uri=mongodb://username:password@host:port/db?ssl=true
如果您只想将 spring 启动应用程序与 mongodb 连接,您可以使用带有 java 代码的 keyStore 和 trustStore。所以你不必通过命令行添加你的证书。如果您使用的是 Cloud Foundry,您可以将您的应用程序与 mongodbServices 连接,然后您在 System.getEnv("VCAP_SERVICES").
中拥有所需的所有凭据
@Configuration
public class MongoConfiguration extends AbstractMongoConfiguration {
private static Log logger = LogFactory.getLog(MongoConfiguration.class);
@Value("${spring.data.mongodb.database}")
private String defaultDatabase; //database you want to connect
private String host;
private int port;
private String authenticationDb; //usually admin
private String username;
private char[] password;
private String certificateDecoded; //your CA Certifcate decoded (starts with BEGIN CERTIFICATE)
public MongoConfiguration() {
//method for credentials initialization
}
//you can't set replicaset=replset in mongooptions so if you want set replicaset, you have to use
// customEditorConfigurer in combintaion with class that implementsPropertyEditorRegistrar
@Bean
public static CustomEditorConfigurer customEditorConfigurer(){
CustomEditorConfigurer configurer = new CustomEditorConfigurer();
configurer.setPropertyEditorRegistrars(
new PropertyEditorRegistrar[]{new ServerAddressPropertyEditorRegistrar()});
return configurer;
}
@Override
protected String getDatabaseName() {
return authenticationDb;
}
@Override
@Bean
public MongoClient mongoClient() {
MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress(host, port)), mongoCredentials(), mongoClientOptions());
return mongoClient;
}
@Bean
public MongoClientOptions mongoClientOptions() {
MongoClientOptions.Builder mongoClientOptions = MongoClientOptions.builder().sslInvalidHostNameAllowed(true).sslEnabled(true);
try {
InputStream inputStream = new ByteArrayInputStream(certificateDecoded.getBytes(StandardCharsets.UTF_8));
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) certificateFactory.generateCertificate(inputStream);
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null); // You don't need the KeyStore instance to come from a file.
keyStore.setCertificateEntry("caCert", caCert);
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
mongoClientOptions.sslContext(sslContext);
mongoClientOptions.sslInvalidHostNameAllowed(true);
} catch (Exception e) {
throw new IllegalStateException(e);
}
return mongoClientOptions.build();
}
private MongoCredential mongoCredentials() {
return MongoCredential.createCredential(username, authenticationDb, password);
}
//With MongoTemplate you have access to db.
@Bean
public MongoTemplate mongoTemplate() {
SimpleMongoDbFactory factory = new SimpleMongoDbFactory(mongoClient(), defaultDatabase);
return new MongoClient(factory);
}
}
public final class ServerAddressPropertyEditorRegistrar implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(ServerAddress[].class, new ServerAddressPropertyEditor());
}
}
Spring 在 Eclipse 中启动 2.3.4 和 Reactive Mongo:
pfx 进入 src/test/resources
@Bean @Profile("dev")
public MongoClientSettings mongoClientSettingsDev() throws NoSuchAlgorithmException {
System.setProperty ("javax.net.ssl.keyStore","target/test-classes/xxx.pfx");
System.setProperty ("javax.net.ssl.keyStorePassword","xxx");
SSLContext sslContext = SSLContext.getDefault();
MongoClientSettings settings = MongoClientSettings.builder()
.applyToSslSettings(builder -> {
builder.enabled(true);
builder.context(sslContext);
})
.build();
return settings;
}
bootstrap.yml 用于连接 x.509:
spring:
data:
mongodb:
database: database_name
uri: mongodb://CN=xxx.xxx.com@cloud.xxx.com:62017/?authMechanism=MONGODB-X509&tls=true&authSource=$external
Spring Boot 2.4.5
更新
@Bean @Profile("dev")
public MongoClientSettings mongoClientSettingsDev(
MongoProperties properties,
Environment environment
) throws NoSuchAlgorithmException {
System.setProperty ("javax.net.ssl.keyStore","target/test-classes/xxx.pfx");
System.setProperty ("javax.net.ssl.keyStorePassword","xxx");
SSLContext sslContext = SSLContext.getDefault();
MongoClientSettings.Builder builder = MongoClientSettings.builder();
builder.applyToSslSettings(b -> {
b.enabled(true);
b.context(sslContext);
});
new MongoPropertiesClientSettingsBuilderCustomizer(properties, environment).customize(builder);
return builder.build();
}
另一种设置 SSLContext 的方法:
Resource resource = new ClassPathResource("xxx.pfx");
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(resource.getInputStream(), "xxx".toCharArray());
SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(ks, "xxx".toCharArray()).build();
如下创建一个 Bean 并在需要的地方使用。
@Configuration
@ComponentScan(basePackages = "XXXXX")
@EnableMongoRepositories({ "XXXXXX" })
public class ApplicationConfig {
System.setProperty ("javax.net.ssl.keyStore", "<CERT>.keystore");
System.setProperty ("javax.net.ssl.keyStorePassword","<password>");
MongoCredential credential = MongoCredential.createMongoX509Credential(
"C=US,ST=XXXXXXX,O=XXXXXX... "
);
MongoClientSettings.Builder settings = MongoClientSettings.builder();
settings.credential(credential);
SSLContext sslContext = SSLContext.getDefault();
MongoClientSettings settings = MongoClientSettings.builder()
.applyToSslSettings(builder -> {
builder.enabled(true);
builder.context(sslContext);}).credential(credential).applyConnectionString(new ConnectionString("mongodb://<host>:<port>/?authMechanism=MONGODB-X509&ssl=true"))
.build();
com.mongodb.client.MongoClient client = MongoClients.create(settings);
SimpleMongoClientDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, <database>);
MongoTemplate mongoTemplate = new MongoTemplate(factory);
return mongoTemplate;
}
}
到目前为止,我还没有找到关于这个话题的好文章explanation/doc。
我正在使用
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.9.5.RELEASE</version>
</dependency>
我的代码如下所示:
@Bean
public MongoClientFactoryBean mongo() {
MongoClientFactoryBean mongo = new MongoClientFactoryBean();
mongo.setHost(host);
mongo.setPort(port);
mongo.setCredentials(new MongoCredential[]{MongoCredential.createCredential(username, database, password.toCharArray())});
return mongo;
}
@Bean
public MongoTemplate mongoTemplate(Mongo mongo) throws Exception {
return new MongoTemplate(mongo, database);
}
你知道我应该如何为此配置 SSL 吗?我可以允许无效证书吗?
等效的 mongo 命令行是
mongo --ssl --sslAllowInvalidCertificates --host <host> --port <port>
文档中有解释:请参考下面:
也可以使用以下配置来启用它
@Bean
public MongoClientOptions mongoClientOptions(){
System.setProperty ("javax.net.ssl.keyStore","<<PATH TO KEYSTOR >>");
System.setProperty ("javax.net.ssl.keyStorePassword","PASSWORD");
MongoClientOptions.Builder builder = MongoClientOptions.builder();
MongoClientOptions options=builder.sslEnabled(true).build();
return options;
}
将 mongo 客户端选项作为参数传递给 MongoClient 实例
public MongoClient(ServerAddress addr, MongoClientOptions options) {
super(addr, options);
}
进一步添加,当 mongo 进程以
启动时mongo --ssl --sslAllowInvalidCertificates --host --port
连接到 mongo 进程的客户端不必设置任何选项来支持它。
您还可以通过以下方式构建启用 ssl 的 mongo 实例。
public @Bean MongoClient mongoClient() throws Exception {
return new MongoClient(new MongoClientURI("mongodb://username:password@host:port/db?ssl=true"));
}
如果您使用 spring 引导,则可以通过以下方式在 application.properties 或 application.yml 中配置
spring.data.mongodb.uri=mongodb://username:password@host:port/db?ssl=true
如果您只想将 spring 启动应用程序与 mongodb 连接,您可以使用带有 java 代码的 keyStore 和 trustStore。所以你不必通过命令行添加你的证书。如果您使用的是 Cloud Foundry,您可以将您的应用程序与 mongodbServices 连接,然后您在 System.getEnv("VCAP_SERVICES").
中拥有所需的所有凭据@Configuration
public class MongoConfiguration extends AbstractMongoConfiguration {
private static Log logger = LogFactory.getLog(MongoConfiguration.class);
@Value("${spring.data.mongodb.database}")
private String defaultDatabase; //database you want to connect
private String host;
private int port;
private String authenticationDb; //usually admin
private String username;
private char[] password;
private String certificateDecoded; //your CA Certifcate decoded (starts with BEGIN CERTIFICATE)
public MongoConfiguration() {
//method for credentials initialization
}
//you can't set replicaset=replset in mongooptions so if you want set replicaset, you have to use
// customEditorConfigurer in combintaion with class that implementsPropertyEditorRegistrar
@Bean
public static CustomEditorConfigurer customEditorConfigurer(){
CustomEditorConfigurer configurer = new CustomEditorConfigurer();
configurer.setPropertyEditorRegistrars(
new PropertyEditorRegistrar[]{new ServerAddressPropertyEditorRegistrar()});
return configurer;
}
@Override
protected String getDatabaseName() {
return authenticationDb;
}
@Override
@Bean
public MongoClient mongoClient() {
MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress(host, port)), mongoCredentials(), mongoClientOptions());
return mongoClient;
}
@Bean
public MongoClientOptions mongoClientOptions() {
MongoClientOptions.Builder mongoClientOptions = MongoClientOptions.builder().sslInvalidHostNameAllowed(true).sslEnabled(true);
try {
InputStream inputStream = new ByteArrayInputStream(certificateDecoded.getBytes(StandardCharsets.UTF_8));
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) certificateFactory.generateCertificate(inputStream);
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null); // You don't need the KeyStore instance to come from a file.
keyStore.setCertificateEntry("caCert", caCert);
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
mongoClientOptions.sslContext(sslContext);
mongoClientOptions.sslInvalidHostNameAllowed(true);
} catch (Exception e) {
throw new IllegalStateException(e);
}
return mongoClientOptions.build();
}
private MongoCredential mongoCredentials() {
return MongoCredential.createCredential(username, authenticationDb, password);
}
//With MongoTemplate you have access to db.
@Bean
public MongoTemplate mongoTemplate() {
SimpleMongoDbFactory factory = new SimpleMongoDbFactory(mongoClient(), defaultDatabase);
return new MongoClient(factory);
}
}
public final class ServerAddressPropertyEditorRegistrar implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(ServerAddress[].class, new ServerAddressPropertyEditor());
}
}
Spring 在 Eclipse 中启动 2.3.4 和 Reactive Mongo:
pfx 进入 src/test/resources
@Bean @Profile("dev")
public MongoClientSettings mongoClientSettingsDev() throws NoSuchAlgorithmException {
System.setProperty ("javax.net.ssl.keyStore","target/test-classes/xxx.pfx");
System.setProperty ("javax.net.ssl.keyStorePassword","xxx");
SSLContext sslContext = SSLContext.getDefault();
MongoClientSettings settings = MongoClientSettings.builder()
.applyToSslSettings(builder -> {
builder.enabled(true);
builder.context(sslContext);
})
.build();
return settings;
}
bootstrap.yml 用于连接 x.509:
spring:
data:
mongodb:
database: database_name
uri: mongodb://CN=xxx.xxx.com@cloud.xxx.com:62017/?authMechanism=MONGODB-X509&tls=true&authSource=$external
Spring Boot 2.4.5
更新 @Bean @Profile("dev")
public MongoClientSettings mongoClientSettingsDev(
MongoProperties properties,
Environment environment
) throws NoSuchAlgorithmException {
System.setProperty ("javax.net.ssl.keyStore","target/test-classes/xxx.pfx");
System.setProperty ("javax.net.ssl.keyStorePassword","xxx");
SSLContext sslContext = SSLContext.getDefault();
MongoClientSettings.Builder builder = MongoClientSettings.builder();
builder.applyToSslSettings(b -> {
b.enabled(true);
b.context(sslContext);
});
new MongoPropertiesClientSettingsBuilderCustomizer(properties, environment).customize(builder);
return builder.build();
}
另一种设置 SSLContext 的方法:
Resource resource = new ClassPathResource("xxx.pfx");
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(resource.getInputStream(), "xxx".toCharArray());
SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(ks, "xxx".toCharArray()).build();
如下创建一个 Bean 并在需要的地方使用。
@Configuration
@ComponentScan(basePackages = "XXXXX")
@EnableMongoRepositories({ "XXXXXX" })
public class ApplicationConfig {
System.setProperty ("javax.net.ssl.keyStore", "<CERT>.keystore");
System.setProperty ("javax.net.ssl.keyStorePassword","<password>");
MongoCredential credential = MongoCredential.createMongoX509Credential(
"C=US,ST=XXXXXXX,O=XXXXXX... "
);
MongoClientSettings.Builder settings = MongoClientSettings.builder();
settings.credential(credential);
SSLContext sslContext = SSLContext.getDefault();
MongoClientSettings settings = MongoClientSettings.builder()
.applyToSslSettings(builder -> {
builder.enabled(true);
builder.context(sslContext);}).credential(credential).applyConnectionString(new ConnectionString("mongodb://<host>:<port>/?authMechanism=MONGODB-X509&ssl=true"))
.build();
com.mongodb.client.MongoClient client = MongoClients.create(settings);
SimpleMongoClientDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, <database>);
MongoTemplate mongoTemplate = new MongoTemplate(factory);
return mongoTemplate;
}
}