SpringCloud Zookeeper 配置用户名密码 源码分析
SpringCloud Zookeeper 配置用户名密码
最近公司为了访问安全,给Zookeeper 设置了用户名密码,这样SpringCloud用Zookeeper 作为注册中心的服务就访问不了,网上搜了很多也没讲如何配置的,都是讲Zookeeper 如何设置密码的。按惯例是解决了,不然也不会心血来潮写个文章来记录下~!
一、SpringCloud注册中心配置
1、引用jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
2、在启动项配置开启注解
@SpringBootApplication
@EnableDiscoveryClient
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3、在application.yml配置参数
# 应用服务端口
server.port: 8080
# 应用名称
spring.application.name: demo-center
# spring-cloud
spring.cloud:
zookeeper.connect-string: 127.0.0.1:2181
loadbalancer:
ribbon.enabled: false
cache.enabled: false
二、源码分析
这样基于Zookeeper为注册中心就配置好了,如果Zookeeper需要用户密码访问再怎么配置,Spring Cloud Zookeeper官网文档介绍:在Zookeeper自动配置类初始化的时候通过CuratorFramework可以设置认证的用户名和密码,请参阅 Zookeeper 自动配置类
Zookeeper 在自动配置的时候生成一个CuratorFramework ,查看CuratorFramework 源码并没有提供addAuthInfo方法(官方文档也有出错的时候~)
@Bean(destroyMethod = "close")
@ConditionalOnMissingBean
public CuratorFramework curatorFramework(RetryPolicy retryPolicy, ZookeeperProperties properties,
ObjectProvider<CuratorFrameworkCustomizer> optionalCuratorFrameworkCustomizerProvider,
ObjectProvider<EnsembleProvider> optionalEnsembleProvider,
ObjectProvider<TracerDriver> optionalTracerDriverProvider) throws Exception {
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder();
EnsembleProvider ensembleProvider = optionalEnsembleProvider.getIfAvailable();
if (ensembleProvider != null) {
builder.ensembleProvider(ensembleProvider);
} else {
builder.connectString(properties.getConnectString());
}
builder.sessionTimeoutMs((int) properties.getSessionTimeout().toMillis())
.connectionTimeoutMs((int) properties.getConnectionTimeout().toMillis())
.retryPolicy(retryPolicy);
optionalCuratorFrameworkCustomizerProvider.orderedStream()
.forEach(curatorFrameworkCustomizer -> curatorFrameworkCustomizer.customize(builder));
CuratorFramework curator = builder.build();
optionalTracerDriverProvider.ifAvailable(tracerDriver -> {
if (curator.getZookeeperClient() != null) {
curator.getZookeeperClient().setTracerDriver(tracerDriver);
}
});
curator.start();
if (log.isTraceEnabled()) {
log.trace("blocking until connected to zookeeper for "+ properties.getBlockUntilConnectedWait() + properties.getBlockUntilConnectedUnit());
}
curator.blockUntilConnected(properties.getBlockUntilConnectedWait(), properties.getBlockUntilConnectedUnit());
if (log.isTraceEnabled()) {
log.trace("connected to zookeeper");
}
return curator;
}
但是通过自动配置代码可以看到CuratorFramework 是通过CuratorFrameworkFactory.Builder生成的,这种是spring常用代码写作技巧,查看源码Builder提供一个authorization和文档上说的一样可以添加用户名和密码。
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder();
builder.authorization("digest", "username :password").getBytes());
可以看到Builder 是方法内部变量,如何在方法外调用到Builder ,或者是直接重写Zookeeper 自动配置再加入authorization;看源码在builder.build()之前,builder对象还被optionalCuratorFrameworkCustomizerProvider调用
optionalCuratorFrameworkCustomizerProvider.orderedStream()
.forEach(curatorFrameworkCustomizer ->
curatorFrameworkCustomizer.customize(builder));
optionalCuratorFrameworkCustomizerProvider是通过Sring容器注入进来的
public CuratorFramework curatorFramework(
RetryPolicy retryPolicy,
ZookeeperProperties properties,
ObjectProvider<CuratorFrameworkCustomizer> optionalCuratorFrameworkCustomizerProvider,
ObjectProvider<EnsembleProvider> optionalEnsembleProvider,
ObjectProvider<TracerDriver> optionalTracerDriverProvider) throws Exception {
由此可见ObjectProvider<CuratorFrameworkCustomizer>
是框架专门开放出来给用户添加个性化属性准备的
@FunctionalInterface
public interface CuratorFrameworkCustomizer {
void customize(CuratorFrameworkFactory.Builder builder);
}
三、配置ZK用户名密码
通过上面的源码解析,我们只要实现CuratorFrameworkCustomizer 注入到Spring容器中,Zookeeper 在自动配置的时候就可以调用到了,上代码:
@Configuration
public class ZookeeperConfigurer implements CuratorFrameworkCustomizer {
@Value("${spring.cloud.zookeeper.username:}")
private String username;
@Value("${spring.cloud.zookeeper.password:}")
private String password;
@Override
public void customize(CuratorFrameworkFactory.Builder builder) {
if (StrUtil.isNotBlank(username) && StrUtil.isNotBlank(password)) {
builder.authorization("digest", (username + ":" + password).getBytes());
}
}
}
这里调用配置文件,如果配置文件配置了用户名密码就配置,如果没有配置就略过,配置文件可以改为
# spring-cloud
spring.cloud:
zookeeper:
connect-string: 127.0.0.1:2181
username: username
password: password
loadbalancer:
ribbon.enabled: false
cache.enabled: false
由此就顺利解决SpringCloud Zookeeper 配置用户名密码 的问题了。
更多推荐
所有评论(0)