Spring Boot 反应式和 mongodb '命令插入需要身份验证'

Posted

技术标签:

【中文标题】Spring Boot 反应式和 mongodb \'命令插入需要身份验证\'【英文标题】:Spring boot reactive and mongodb 'command insert requires authentication'Spring Boot 反应式和 mongodb '命令插入需要身份验证' 【发布时间】:2020-11-16 07:14:28 【问题描述】:

我在 docker 容器中使用 Spring Boot 2.3.1 和 webflux 和 MongoDB 创建了一个项目。项目正常启动并使用 application.properties 中声明的参数在 MongoDB 中连接。

当我尝试执行 CRUD 操作“插入”时,问题就开始了。生成以下日志:

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)

阅读Spring Data MongoDB Reference Documentation,我按照建议为 mongodb 配置创建了一个自定义 Bean:

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

我尝试了 MongoClientReactiveMongoDatabaseFactory,但我无法执行 save 方法。总是返回'命令插入需要身份验证'

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

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

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

我在这里做错了什么?如何配置此 Spring Boot 反应式应用程序以与 mongodb 正确集成?

提前致谢。

【问题讨论】:

你应该在你的 properties/yaml 文件 spring.data.mongodb.uri=spring.data.mongodb.uri=mongodb://root:root@localhost:27017/ 中有这样的属性test 你也能做读操作吗? MongoDB 自动配置将为您设置客户端。 @DhruvG 感谢您的回复,很抱歉长时间回复。我删除了 mongoClient 方法并留下来实例化客户端,我在 application.properties 中添加了 uri 属性,就像您的示例一样。在此之后,错误发生了变化。现在是: 引起:com.mongodb.MongoSecurityException:异常验证 MongoCredentialmechanism=SCRAM-SHA-256, userName='exampleapp', source='exampledb', password=,mechanismProperties=;我做了其他更改,添加到 docker-compose "command: "--bind_ip_all" " 以允许其他请求来源。 【参考方案1】:

如果您仍然遇到此问题。我有一个类似的问题,并通过使用 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");
    

【讨论】:

感谢您的回复。正如@DhruvG 所建议的那样,我删除了客户端实例化并留给弹簧自动配置它。如果没有启用 mongodb 身份验证,则效果很好,但是,如果启用了 mongodb 身份验证,则 spring boot 在启动时连接,但在尝试执行插入时失败。你如何使用 reactiveMongoClient() 进行配置? 哥们,你太棒了!从字面上看,花了 1 周的时间才完成这项工作,经过几次失败的尝试,现在终于成功了。

以上是关于Spring Boot 反应式和 mongodb '命令插入需要身份验证'的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot 反应式和 EventSource 的工作示例

Spring Data (数据)MongoDB

spring-boot mongodb 4.0 兼容性

Spring Boot 和 Spring Data MongoDB:在 ResponseBody 中隐藏字段

如何配置两个实例mongodb使用spring boot和spring data

使用 Spring Boot 和 mongodb 运行 camunda