paulwong

          Spring Boot Data Mongodb Starter自動配置那些坑

          正好做Mongodb主從復(fù)制嘗試使用Spring Boot Data Mongodb Starter插件鏈接訪問Mongodb數(shù)據(jù)庫集群。

          遇到的坑:

          • spring.data.mongodb.host和spring.data.mongodb.port形式不適合集群配置,會報host無法識別異常
          • spring.data.mongodb.uri中經(jīng)常拋出authentication failed異常


          解決辦法:

          1.  對于第一個坑,請使用spring.data.mongodb.uri。如果使用了uri,則其余的host/username/password/db/auth-db這些全部無效。
          2.  對于第二個坑,請?jiān)趕pring.data.mongodb.uri中指定replicaSet和authsource,另外記得把所有集群節(jié)點(diǎn)服務(wù)器地址都列全。
            如果auth-db和db是同一個,則無需加authsource,如果不同,則加authsource=admin


          我沒有把a(bǔ)uthsource指定,所以一直報authentication failed異常。然后只好一點(diǎn)點(diǎn)去發(fā)掘問題點(diǎn),最后查到在com.mongodb.ConnectionString類中的createCredentials中

          private MongoCredential createCredentials(final Map<String, List<String>> optionsMap, final String userName,
                                                        final char[] password) {
                  AuthenticationMechanism mechanism = null;
                  String authSource = (database == null) ? "admin" : database;
                  String gssapiServiceName = null;
                  String authMechanismProperties = null;

                  for (final String key : AUTH_KEYS) {
                      String value = getLastValue(optionsMap, key);

                      if (value == null) {
                          continue;
                      }

                      if (key.equals("authmechanism")) {
                          mechanism = AuthenticationMechanism.fromMechanismName(value);
                      } else if (key.equals("authsource")) {
                          authSource = value;
                      } else if (key.equals("gssapiservicename")) {
                          gssapiServiceName = value;
                      } else if (key.equals("authmechanismproperties")) {
                          authMechanismProperties = value;
                      }
                  }


                  MongoCredential credential = null;
                  if (mechanism != null) {
                      switch (mechanism) {
                          case GSSAPI:
                              credential = MongoCredential.createGSSAPICredential(userName);
                              if (gssapiServiceName != null) {
                                  credential = credential.withMechanismProperty("SERVICE_NAME", gssapiServiceName);
                              }
                              break;
                          case PLAIN:
                              credential = MongoCredential.createPlainCredential(userName, authSource, password);
                              break;
                          case MONGODB_CR:
                              credential = MongoCredential.createMongoCRCredential(userName, authSource, password);
                              break;
                          case MONGODB_X509:
                              credential = MongoCredential.createMongoX509Credential(userName);
                              break;
                          case SCRAM_SHA_1:
                              credential = MongoCredential.createScramSha1Credential(userName, authSource, password);
                              break;
                          default:
                              throw new UnsupportedOperationException(format("The connection string contains an invalid authentication mechanism'. "
                                                                                     + "'%s' is not a supported authentication mechanism",
                                      mechanism));
                      }
                  } else if (userName != null) {
                      credential = MongoCredential.createCredential(userName, authSource, password);
                  }

                  if (credential != null && authMechanismProperties != null) {
                      for (String part : authMechanismProperties.split(",")) {
                          String[] mechanismPropertyKeyValue = part.split(":");
                          if (mechanismPropertyKeyValue.length != 2) {
                              throw new IllegalArgumentException(format("The connection string contains invalid authentication properties. "
                                      + "'%s' is not a key value pair", part));
                          }
                          String key = mechanismPropertyKeyValue[0].trim().toLowerCase();
                          String value = mechanismPropertyKeyValue[1].trim();
                          if (key.equals("canonicalize_host_name")) {
                              credential = credential.withMechanismProperty(key, Boolean.valueOf(value));
                          } else {
                              credential = credential.withMechanismProperty(key, value);
                          }
                      }
                  }
                  return credential;
              }


          authSource默認(rèn)會指向我們目標(biāo)數(shù)據(jù)的數(shù)據(jù)庫。然而在身份驗(yàn)證機(jī)制中我們通常需要指向admin。(非常想報粗口,代碼作者在這里腦袋被men擠了么)。所以需要強(qiáng)制指定authSource中指定。具體指定方式如下:

           

           

           

           

          mongodb://{用戶名}:{密碼}@{host1}:27017,{host2}:27017,{host3}:27017/{目標(biāo)數(shù)據(jù)庫}?replicaSet={復(fù)制集名稱}&write=1&readPreference=primary&authsource={授權(quán)數(shù)據(jù)庫}

          posted on 2020-03-17 09:39 paulwong 閱讀(1963) 評論(0)  編輯  收藏 所屬分類: MONGODBSPRING BOOT

          主站蜘蛛池模板: 浦江县| 都安| 双峰县| 建阳市| 德安县| 会宁县| 九龙县| 读书| 洪洞县| 黄平县| 兴文县| 历史| 观塘区| 印江| 崇信县| 时尚| 普安县| 崇州市| 泸州市| 休宁县| 乾安县| 延长县| 上林县| 锦州市| 淳化县| 武穴市| 虹口区| 贵南县| 永定县| 南开区| 防城港市| 鹿泉市| 临朐县| 岗巴县| 时尚| 牙克石市| 庆云县| 靖西县| 华蓥市| 广宁县| 砚山县|