春季引导响应式和MongoDB:“command insert requires authentication”

huangapple go评论81阅读模式
英文:

Spring boot reactive and mongodb 'command insert requires authentication'

问题

我使用了 Spring Boot 2.3.1 与 webflux 以及 MongoDB 在 Docker 容器中创建了一个项目。项目能够正常启动,并使用在 application.properties 文件中声明的参数连接到 MongoDB。

问题出现在我尝试执行 CRUD 操作中的“插入”操作时。生成了以下日志:

500 Server Error for HTTP POST "/configuracao"

org.springframework.data.mongodb.UncategorizedMongoDbException: 在服务器 127.0.0.1:27017 上命令执行失败,错误代码为 13(未经授权):'command insert requires authentication'。完整响应为{"ok": 0.0, "errmsg": "command insert requires authentication", "code": 13, "codeName": "Unauthorized"};嵌套异常为 com.mongodb.MongoCommandException: 在服务器 127.0.0.1:27017 上命令执行失败,错误代码为 13(未经授权):'command insert requires authentication'。完整响应为{"ok": 0.0, "errmsg": "command insert requires authentication", "code": 13, "codeName": "Unauthorized"}
	at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:133) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
	......

我根据 Spring Data MongoDB 参考文档 创建了一个自定义的 Bean 用于 MongoDB 配置,代码如下:

@Configuration
@EnableTransactionManagement
@EnableReactiveMongoRepositories
public class MongoConfiguration extends AbstractReactiveMongoConfiguration {

    @Value("${spring.data.mongodb.database}")
    private String database;

    @Bean
    public MongoClient mongoClient() {
        return MongoClients.create("mongodb://exampleapp:example@localhost:27017/exampledb");
    }

    @Override
    protected String getDatabaseName() {
        return database;
    }
}

我尝试过使用 MongoClientReactiveMongoDatabaseFactory,但无法执行 save 方法。始终返回“'command insert requires authentication'”。

对于 Docker 容器,我在容器启动后使用以下脚本初始化数据库:

db.auth('mongoadmin', 'mongoadmin')
db = db.getSiblingDB('exampledb')
db.createUser(
    {
        user: "exampleapp",
        pwd: "example",
        roles: [
            {
                role: "readWrite",
                db: "exampledb"
            }
        ]
    }
)

应用程序可以在启动时成功连接,我可以使用 mongo-express 或其他图形界面工具连接到数据库。

我在这里做错了什么?我如何配置这个 Spring Boot 反应式应用程序才能与 MongoDB 正确集成?

提前感谢您的回答。

英文:

I created a project using Spring Boot 2.3.1 with webflux and MongoDB in a docker container. The project starts normally and connect in MongoDB with the params declared in application.properties.

The problem beggins when I try execute a CRUD operation "insert". The following log is generated:

500 Server Error for HTTP POST "/configuracao"

org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 13 (Unauthorized): 'command insert requires authentication' on server 127.0.0.1:27017. The full response is {"ok": 0.0, "errmsg": "command insert requires authentication", "code": 13, "codeName": "Unauthorized"}; nested exception is com.mongodb.MongoCommandException: Command failed with error 13 (Unauthorized): 'command insert requires authentication' on server 127.0.0.1:27017. The full response is {"ok": 0.0, "errmsg": "command insert requires authentication", "code": 13, "codeName": "Unauthorized"}
	at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:133) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Assembly trace from producer [reactor.core.publisher.MonoError] :
	reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onError(MonoFlatMapMany.java:247)
	com.mongodb.reactivestreams.client.internal.AbstractSubscription.onError(AbstractSubscription.java:139)
Error has been observed at the following site(s):
	|_ MonoFlatMapMany$FlatMapManyInner.onError ⇢ at com.mongodb.reactivestreams.client.internal.AbstractSubscription.onError(AbstractSubscription.java:139)
	|_                          Flux.onErrorMap ⇢ at org.springframework.data.mongodb.core.ReactiveMongoTemplate.createFlux(ReactiveMongoTemplate.java:651)
	|_                                Flux.last ⇢ at org.springframework.data.mongodb.core.ReactiveMongoTemplate.insertDocument(ReactiveMongoTemplate.java:1578)
	|_                                 Mono.map ⇢ at org.springframework.data.mongodb.core.ReactiveMongoTemplate.insertDocument(ReactiveMongoTemplate.java:1578)
	|_                             Mono.flatMap ⇢ at org.springframework.data.mongodb.core.ReactiveMongoTemplate.lambda$doInsert$35(ReactiveMongoTemplate.java:1344)
	|_                             Mono.flatMap ⇢ at org.springframework.data.mongodb.core.ReactiveMongoTemplate.doInsert(ReactiveMongoTemplate.java:1342)
	|_                                 Mono.map ⇢ at org.springframework.http.codec.json.AbstractJackson2Encoder.encode(AbstractJackson2Encoder.java:120)
	|_                                Mono.flux ⇢ at org.springframework.http.codec.json.AbstractJackson2Encoder.encode(AbstractJackson2Encoder.java:121)
	|_                       Flux.singleOrEmpty ⇢ at org.springframework.http.codec.EncoderHttpMessageWriter.write(EncoderHttpMessageWriter.java:121)
	|_                       Mono.switchIfEmpty ⇢ at org.springframework.http.codec.EncoderHttpMessageWriter.write(EncoderHttpMessageWriter.java:122)
	|_                             Mono.flatMap ⇢ at org.springframework.http.codec.EncoderHttpMessageWriter.write(EncoderHttpMessageWriter.java:126)
	|_                               checkpoint ⇢ Handler br.com.example.exampleapplication.controller.ConfiguracaoController#save(Configuracao) [DispatcherHandler]
	|_                             Mono.flatMap ⇢ at org.springframework.web.reactive.DispatcherHandler.lambda$handleResult$5(DispatcherHandler.java:172)
	|_                       Mono.onErrorResume ⇢ at org.springframework.web.reactive.DispatcherHandler.handleResult(DispatcherHandler.java:171)
	|_                             Mono.flatMap ⇢ at org.springframework.web.reactive.DispatcherHandler.handle(DispatcherHandler.java:147)
	|_                               Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:119)
	|_                         Mono.doOnSuccess ⇢ at org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter.filter(MetricsWebFilter.java:78)
	|_                           Mono.doOnError ⇢ at org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter.filter(MetricsWebFilter.java:79)
	|_                   Mono.transformDeferred ⇢ at org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter.filter(MetricsWebFilter.java:73)
	|_                               checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
	|_                               Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:119)
	|_                               Mono.error ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler$CheckpointInsertingHandler.handle(ExceptionHandlingWebHandler.java:98)
	|_                               checkpoint ⇢ HTTP POST "/configuracao" [ExceptionHandlingWebHandler]
	|_                       Mono.onErrorResume ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler.handle(ExceptionHandlingWebHandler.java:77)

Reading the Spring Data MongoDB Reference Documentation, I create a custom Bean for mongodb config as suggested:

@Configuration
@EnableTransactionManagement
@EnableReactiveMongoRepositories
public class MongoConfiguration extends AbstractReactiveMongoConfiguration {

    @Value("${spring.data.mongodb.database}")
    private String database;

    @Bean
    public MongoClient mongoClient() {
        return MongoClients.create("mongodb://exampleapp:example@localhost:27017/exampledb");
    }

//    @Bean
//    public ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory() {
//        return new SimpleReactiveMongoDatabaseFactory(MongoClients.create("mongodb://exampleapp:example@localhost:27017/exampledb"), database);
//    }

    @Override
    protected String getDatabaseName() {
        return database;
    }

I tried with MongoClient and with ReactiveMongoDatabaseFactory and I can't execute the save method. Always is returned that 'command insert requires authentication'.

For the docker container I'm using this script to initialize the database after container startup:

db.auth('mongoadmin', 'mongoadmin')
db = db.getSiblingDB('exampledb')
db.createUser(
    {
        user: "exampleapp",
        pwd: "example",
        roles: [
            {
                role: "readWrite",
                db: "exampledb"
            }
        ]
    }
)

The application connects successfully on the startup, I can connect on the database using mongo-express or another gui tool.

What I doing wrong here? How I can configure this spring boot reactive app to propperly integrate with mongodb?

Thanks in advance.

答案1

得分: 4

如果您仍然遇到此问题,我曾经有一个类似的问题,并通过使用reactiveMongoClient()来解决它,而不是mongoClient()

替换:

@Bean
public MongoClient mongoClient() {
    return MongoClients.create("mongodb://exampleapp:example@localhost:27017/exampledb");
}

使用:

@Override
public MongoClient reactiveMongoClient() {
    return MongoClients.create("mongodb://exampleapp:example@localhost:27017/exampledb");
}

您的Bean应该如下所示:

@EnableReactiveMongoRepositories
@Slf4j
public class MongoDBCConfig extends AbstractReactiveMongoConfiguration {

    @Override
    protected String getDatabaseName() {
        return "dbname";
    }

    @Override
    public MongoClient reactiveMongoClient() {
        return MongoClients.create("mongodb://username:password@localhost:27017/authSource=auth-source");
    }
}
英文:

In case you are still having this issue. I had a similar problem and resolved it by using reactiveMongoClient() instead of mongoClient().

Replace:

 @Bean
public MongoClient mongoClient() {
    return MongoClients.create("mongodb://exampleapp:example@localhost:27017/exampledb");
}

With:

@Override
public MongoClient reactiveMongoClient() {
    return MongoClients.create("mongodb://exampleapp:example@localhost:27017/exampledb");
}

Your bean should look like:

@EnableReactiveMongoRepositories
@Slf4j
public class MongoDBCConfig extends 
AbstractReactiveMongoConfiguration {

@Override
protected String getDatabaseName() {
    return "dbname";
}

@Override
public MongoClient reactiveMongoClient() {
    return MongoClients.create("mongodb://username:password@localhost:27017/authSource=auth-source");
    }
}

huangapple
  • 本文由 发表于 2020年7月27日 08:22:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/63107149.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定