最近公司为了访问安全,给Zookeeper 设置了用户名密码,这样SpringCloud用Zookeeper 作为注册中心的服务就访问不了,网上搜了很多也没讲如何配置的,都是讲Zookeeper 如何设置密码的。按惯例是解决了,不然也不会心血来潮写个文章来记录下~!
一、SpringCloud注册中心配置
1、引用jar包
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zookeeper-discovery</artifactId></dependency>
2、在启动项配置开启注解
@SpringBootApplication@EnableDiscoveryClientpublicclassDemoApplication{publicstaticvoidmain(String[] args){SpringApplication.run(DemoApplication.class, args);}}
3、在application.yml配置参数
# 应用服务端口server.port:8080# 应用名称spring.application.name: demo-center
# spring-cloudspring.cloud:zookeeper.connect-string: 127.0.0.1:2181loadbalancer:ribbon.enabled:falsecache.enabled:false
二、源码分析
这样基于Zookeeper为注册中心就配置好了,如果Zookeeper需要用户密码访问再怎么配置,Spring Cloud Zookeeper官网文档介绍:在Zookeeper自动配置类初始化的时候通过CuratorFramework可以设置认证的用户名和密码,请参阅 Zookeeper 自动配置类
Zookeeper 在自动配置的时候生成一个CuratorFramework ,查看CuratorFramework 源码并没有提供addAuthInfo方法(官方文档也有出错的时候~)
@Bean(destroyMethod ="close")@ConditionalOnMissingBeanpublicCuratorFrameworkcuratorFramework(RetryPolicy retryPolicy,ZookeeperProperties properties,ObjectProvider<CuratorFrameworkCustomizer> optionalCuratorFrameworkCustomizerProvider,ObjectProvider<EnsembleProvider> optionalEnsembleProvider,ObjectProvider<TracerDriver> optionalTracerDriverProvider)throwsException{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容器注入进来的
publicCuratorFrameworkcuratorFramework(RetryPolicy retryPolicy,ZookeeperProperties properties,ObjectProvider<CuratorFrameworkCustomizer> optionalCuratorFrameworkCustomizerProvider,ObjectProvider<EnsembleProvider> optionalEnsembleProvider,ObjectProvider<TracerDriver> optionalTracerDriverProvider)throwsException{
由此可见
ObjectProvider<CuratorFrameworkCustomizer>
是框架专门开放出来给用户添加个性化属性准备的
@FunctionalInterfacepublicinterfaceCuratorFrameworkCustomizer{voidcustomize(CuratorFrameworkFactory.Builder builder);}
三、配置ZK用户名密码
通过上面的源码解析,我们只要实现CuratorFrameworkCustomizer 注入到Spring容器中,Zookeeper 在自动配置的时候就可以调用到了,上代码:
@ConfigurationpublicclassZookeeperConfigurerimplementsCuratorFrameworkCustomizer{@Value("${spring.cloud.zookeeper.username:}")privateString username;@Value("${spring.cloud.zookeeper.password:}")privateString password;@Overridepublicvoidcustomize(CuratorFrameworkFactory.Builder builder){if(StrUtil.isNotBlank(username)&&StrUtil.isNotBlank(password)){
builder.authorization("digest",(username +":"+ password).getBytes());}}}
这里调用配置文件,如果配置文件配置了用户名密码就配置,如果没有配置就略过,配置文件可以改为
# spring-cloudspring.cloud:zookeeper:connect-string: 127.0.0.1:2181username: username
password: password
loadbalancer:ribbon.enabled:falsecache.enabled:false
由此就顺利解决SpringCloud Zookeeper 配置用户名密码 的问题了。
版权归原作者 Return_Code 所有, 如有侵权,请联系我们删除。