【问题标题】:Spring data mongodb, how to set SSL?Spring data mongodb,如何设置SSL?
【发布时间】:2017-01-05 18:26:42
【问题描述】:

到目前为止,我还没有找到关于该主题的好的解释/文档。

我正在使用

<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>

【问题讨论】:

  • 我看到所有答案都表明“javax.net.ssl.keyStore”这实际上是不正确的,因为它是更改密钥库的信任库,所以您应该使用 System.setProperty ("javax .net.ssl.trustStore",""); System.setProperty("javax.net.ssl.trustStorePassword","");或者使用(Java 9 及更高版本)将 cacert 添加到 java trustsrore: keytool -importcert -trustcacerts -cacerts -file ca-certificate.crt -alias your-alias

标签: spring mongodb spring-data-mongodb


【解决方案1】:

如果你只是想将你的 spring boot 应用与 mongodb 连接,你可以使用 java 代码中的 keyStore 和 trustStore。所以你不必通过命令行添加你的证书。如果您使用云代工,您可以将您的应用程序与 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());
    }
}

【讨论】:

    【解决方案2】:

    Spring Boot 2.3.4 和 Eclipse 中的 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;
      }
    

    用于与 x.509 连接的 bootstrap.yml:

    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();
    

    【讨论】:

    • 这成功了!非常感谢。但是,我不得不将 javax.net.ssl.keyStorejavax.net.ssl.keyStorePassword 更改为以下属性 - javax.net.ssl.trustStorejavax.net.ssl.trustStorePassword
    • 感谢您发布 Spring Boot 2.4.5 更新!
    【解决方案3】:

    文档中有说明:请参考以下内容:

    http://mongodb.github.io/mongo-java-driver/3.0/driver/reference/connecting/ssl/?_ga=1.122423051.1001600813.1475930911

    也可以使用下面的配置来启用它

        @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 进程以

    启动时

    蒙哥 --ssl --sslAllowInvalidCertificates --host --port

    连接到 mongo 进程的客户端不必设置任何选项来支持这一点。

    【讨论】:

    • 我认为您的评论对库“mongo-java-driver”有效,而不是对“spring-data-mongodb”库有效。这个回复似乎更适合stackoverflow.com/a/60168414/7658979这个问题
    • @Alessandro 点数。将尝试根据您的 cmets 进行更新,谢谢!
    【解决方案4】:

    您还可以通过以下方式构建启用 ssl 的 mongo 实例。

    public @Bean MongoClient mongoClient() throws Exception {
        return new MongoClient(new MongoClientURI("mongodb://username:password@host:port/db?ssl=true"));
    }
    

    如果你使用spring boot,那么它可以通过以下方式在application.properties或application.yml中进行配置

    spring.data.mongodb.uri=mongodb://username:password@host:port/db?ssl=true
    

    【讨论】:

      【解决方案5】:

      如下创建一个 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;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-06
        • 2016-12-10
        • 2021-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-29
        相关资源
        最近更新 更多