mongodb 3.0出来了, 有多了很多新特性. 不过这不是我要说的 . 如果要在Java应用程序里用mongodb 3.0你得用3.0的Java驱动程序. 旧的是不行的. 然而很多Java的库还没有跟上脚步, 用的是2.6的驱动程序. Spring Boot就是其中之一. 我相信过不了多久, Spring Boot就会升级支持3.0. 那么现在如果想要用mongodb 3.0怎办呢? 首先你需要把maven的依赖改成3.0相关的版本:
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>1.7.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-commons</artifactId>
    <version>1.10.0.RELEASE</version>
</dependency>
然后以Spring Boot为例, 你要配置mongodb连接的参数 (application.yaml)
spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      username: user
      password: abc123
      database: zen
      authenticationDatabase: zen
我在mongodb 3.0里已经创建了一个数据库叫zen, 并且给zen创建了一个用户user, 密码是abc123 然后我设置mongodb的auth=true 在2.6开始可以用yaml的方式配置:
security:
    authorization: enabled
按照Spring Boot的文档, 有了以上配置后, 你就可以使用Mongodb了, 比如用MongodbTemplate访问数据库. 而实际上如果是3.0那么数据库会告诉你认证失败. 这个问题困扰了很久, 最后还是查看Spring Boot的源码才发现, 原来MongoDB 3.0新增了一种认证机制(authenticationMechanisms) SCRAM-SHA-1, 并把他设置为默认的方式. 而Spring Boot里默认使用旧的认证机制. 这就造成了不一致从而认证通不过. 解决方法有两种: 1. 把Mongodb的认证机制改了: mongodb支持如下几种:
SCRAM-SHA-1	
MONGODB-CR
MONGODB-X509
GSSAPI (Kerberos)
PLAIN (LDAP SASL)
把Mongodb的认证方式改变一下自然能解决问题. 可以同时支持多个.
setParameter:
    authenticationMechanisms: MONGODB-CR,SCRAM-SHA-1
    enableLocalhostAuthBypass: false
    logLevel: 4
但是既然MongoDB从3.0开始用SCRAM-SHA-1作为默认,应该是有道理的, 比如安全性方面比MONGODB-CR更好之类的.
引用
MongoDB’s implementation of SCRAM-SHA-1 represents an improvement in security over the previously-used MONGODB-CR, providing: * A tunable work factor (iterationCount), * Per-user random salts rather than server-wide salts, * A cryptographically stronger hash function (SHA-1 rather than MD5), and * Authentication of the server to the client as well as the client to the server.
2. 如果你不行改变认证方式, 就只能改java代码了 我们看一下Spring Boot的源码; org.springframework.boot.autoconfigure.mongo.MongoProperties 的 createMongoClient方法:
public MongoClient createMongoClient(MongoClientOptions options)
		throws UnknownHostException {
	try {
		if (hasCustomAddress() || hasCustomCredentials()) {
			if (options == null) {
				options = MongoClientOptions.builder().build();
			}
			List<MongoCredential> credentials = null;
			if (hasCustomCredentials()) {
				String database = this.authenticationDatabase == null ? getMongoClientDatabase()
						: this.authenticationDatabase;
				credentials = Arrays.asList(MongoCredential.createMongoCRCredential(
						this.username, database, this.password));
			}
			String host = this.host == null ? "localhost" : this.host;
			int port = this.port == null ? DEFAULT_PORT : this.port;
			return new MongoClient(Arrays.asList(new ServerAddress(host, port)),
					credentials, options);
		}
		// The options and credentials are in the URI
		return new MongoClient(new MongoClientURI(this.uri, builder(options)));
	}
	finally {
		clearPassword();
	}
}
可以看到它是用MongoCredential.createMongoCRCredential方法来创建认证信息, 并且没有留出任何公开的接口让你改变这一行为. 这个真是不应该呀. 找到问题所在, 其实解决就非常方便了, 使用createScramSha1Credential方法既可. 但是就像上面说的, 没有公开接口, 只能把MongoProperties复制一份, 然后改这一行代码了 首先创建一个MongoDBConfiguration类, 用于创建MongoClient实例.
@Configuration
@EnableConfigurationProperties(MongoProperties.class)
public class MongoDBConfiguration {
    @Autowired
    private MongoProperties properties;
    @Autowired(required = false)
    private MongoClientOptions options;
    private Mongo mongo;
    @PreDestroy
    public void close() {
        if (this.mongo != null) {
            this.mongo.close();
        }
    }
    @Bean
    public Mongo mongo() throws UnknownHostException {
        this.mongo = this.properties.createMongoClient(this.options);
        return this.mongo;
    }
}
细心的程序猿们会发现一个问题: Spring Boot中不是有一个一模一样的类吗? 是啊. 但是没法直接用那个类(在org.springframework.boot.autoconfigure.mongo包), 因为它里面用的是同一个包下的MongoProperties, 而不会使用你的. 然后就是我们自己的MongoProperties类了, 我就不写了, 就上面那一句话不一样, 还有就是要让MongoDBConfiguration引用我们自己的MongoProperties类. 然后就OK了. 其实如果Spring Boot做的完善一点应该提供可以选择认证机制的功能, 或者提供公开接口实现自己的认证功能
你可能感兴趣的内容
0条评论

dexcoder

这家伙太懒了 <( ̄ ﹌  ̄)>
Owner