分布式服務(wù)Dubbo+Zookeeper安全認(rèn)證:KeeperErrorCode = NoAuth

一皇忿、問(wèn)題背景:

我們Zookeeper正常的情況下是部署在內(nèi)網(wǎng)進(jìn)行服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)暖眼,難免有一些特許的情況需要部署到外網(wǎng)酣倾。而部署到外網(wǎng)的中我們需要對(duì)于服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)進(jìn)行安全認(rèn)證苗桂。至于怎樣進(jìn)行安全配置就不詳細(xì)的描述矗烛,可以參考這篇文章(https://www.cnblogs.com/smallSevens/p/8064995.html
在Dubbo registry上配置相應(yīng)的用戶玫镐、密碼倒戏,服務(wù)就注冊(cè)不到Zookeeper上了,會(huì)報(bào)KeeperErrorCode = NoAuth錯(cuò)誤恐似。

二杜跷、問(wèn)題分析

代碼分析
  • Dubbo創(chuàng)建注冊(cè)zookeeper是通過(guò)工廠模式,而這個(gè)工廠類(lèi)就是RegistryFactory矫夷,在這個(gè)工廠類(lèi)中Dubbo提供了一個(gè)抽象實(shí)現(xiàn)類(lèi)
    AbstractRegistryFactory葛闷,AbstractRegistryFactory實(shí)現(xiàn)了getRegistry方法,并將具體的創(chuàng)建ZookeeperRegistry細(xì)節(jié)由子類(lèi)工廠進(jìn)行實(shí)現(xiàn)双藕,在Dubbo使用ZookeeperRegistryFactory子類(lèi)進(jìn)行創(chuàng)建zookeeper連接和注冊(cè)淑趾。
AbstractRegistryFactory.java

public Registry getRegistry(URL url) {
        url = url.setPath(RegistryService.class.getName())
                .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName())
                .removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY);
        String key = url.toServiceString();
        // 鎖定注冊(cè)中心獲取過(guò)程,保證注冊(cè)中心單一實(shí)例
        LOCK.lock();
        try {
            Registry registry = REGISTRIES.get(key);
            if (registry != null) {
                return registry;
            }
            registry = createRegistry(url);
            if (registry == null) {
                throw new IllegalStateException("Can not create registry " + url);
            }
            REGISTRIES.put(key, registry);
            return registry;
        } finally {
            // 釋放鎖
            LOCK.unlock();
        }
    }
ZookeeperRegistryFactory.java

public class ZookeeperRegistryFactory extends AbstractRegistryFactory {
    
    private ZookeeperTransporter zookeeperTransporter;

    public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
        this.zookeeperTransporter = zookeeperTransporter;
    }

    public Registry createRegistry(URL url) {
        return new ZookeeperRegistry(url, zookeeperTransporter);
    }

}
  • 我們通過(guò)ZookeeperRegistry發(fā)現(xiàn)zookeeper的連接是通過(guò)zookeeperTransporter進(jìn)行創(chuàng)建忧陪。
public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
        super(url);
        if (url.isAnyHost()) {
            throw new IllegalStateException("registry address == null");
        }
        String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
        if (! group.startsWith(Constants.PATH_SEPARATOR)) {
            group = Constants.PATH_SEPARATOR + group;
        }
        this.root = group;
        zkClient = zookeeperTransporter.connect(url);
        zkClient.addStateListener(new StateListener() {
            public void stateChanged(int state) {
                if (state == RECONNECTED) {
                    try {
                        recover();
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
        });
    }
  • zookeeperTransporter是一個(gè)接口扣泊,而該接口提供了兩種實(shí)現(xiàn):CuratorZookeeperTransporter和ZkclientZookeeperTransporter近范,而這兩個(gè)實(shí)現(xiàn)類(lèi)分別創(chuàng)建CuratorZookeeperClient和ZkclientZookeeperClient。
public class CuratorZookeeperTransporter implements ZookeeperTransporter {

    public ZookeeperClient connect(URL url) {
        return new CuratorZookeeperClient(url);
    }

}
public class ZkclientZookeeperTransporter implements ZookeeperTransporter {

    public ZookeeperClient connect(URL url) {
        return new ZkclientZookeeperClient(url);
    }
}
  • 通過(guò)對(duì)CuratorZookeeperClient和ZkclientZookeeperClient的構(gòu)造方法發(fā)現(xiàn)延蟹,ZkclientZookeeperClient是沒(méi)有進(jìn)行設(shè)置zookeeper的auth的賬號(hào)和密碼评矩。
public ZkclientZookeeperClient(URL url) {
        super(url);
        client = new ZkClient(
                url.getBackupAddress(),
                url.getParameter(Constants.SESSION_TIMEOUT_KEY, Constants.DEFAULT_SESSION_TIMEOUT),
                url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_REGISTRY_CONNECT_TIMEOUT));
        client.subscribeStateChanges(new IZkStateListener() {
            public void handleStateChanged(KeeperState state) throws Exception {
                ZkclientZookeeperClient.this.state = state;
                if (state == KeeperState.Disconnected) {
                    stateChanged(StateListener.DISCONNECTED);
                } else if (state == KeeperState.SyncConnected) {
                    stateChanged(StateListener.CONNECTED);
                }
            }
            public void handleNewSession() throws Exception {
                stateChanged(StateListener.RECONNECTED);
            }
        });
    }
public CuratorZookeeperClient(URL url) {
        super(url);
        Builder builder = CuratorFrameworkFactory.builder()
                .connectString(url.getBackupAddress())
                .retryPolicy(new RetryNTimes(Integer.MAX_VALUE, 1000))
                .connectionTimeoutMs(url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_REGISTRY_CONNECT_TIMEOUT))
                .sessionTimeoutMs(url.getParameter(Constants.SESSION_TIMEOUT_KEY, Constants.DEFAULT_SESSION_TIMEOUT));
   //設(shè)置zookeeper的auth賬號(hào)和密碼。
        String authority = url.getAuthority();
        if (authority != null && authority.length() > 0) {
            builder = builder.authorization("digest", authority.getBytes());
        }
        client = builder.build();
        client.getConnectionStateListenable().addListener(
                new ConnectionStateListener() {
                    public void stateChanged(CuratorFramework client,
                            ConnectionState state) {
                        if (state == ConnectionState.LOST) {
                            CuratorZookeeperClient.this
                                    .stateChanged(StateListener.DISCONNECTED);
                        } else if (state == ConnectionState.CONNECTED) {
                            CuratorZookeeperClient.this
                                    .stateChanged(StateListener.CONNECTED);
                        } else if (state == ConnectionState.RECONNECTED) {
                            CuratorZookeeperClient.this
                                    .stateChanged(StateListener.RECONNECTED);
                        }
                    }
                });
        c

總結(jié):通過(guò)源碼的分析發(fā)現(xiàn)使用ZkclientZookeeperClient進(jìn)行連接zookeeper和注冊(cè)服務(wù)是不會(huì)設(shè)置安全配置阱飘。

三稚照、解決方案

將dubbo.registry.client由zkclient改為curator即可。dubbo.registry.client = curator

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末俯萌,一起剝皮案震驚了整個(gè)濱河市果录,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咐熙,老刑警劉巖弱恒,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異棋恼,居然都是意外死亡返弹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)爪飘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)义起,“玉大人,你說(shuō)我怎么就攤上這事师崎∧眨” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵犁罩,是天一觀的道長(zhǎng)齐蔽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)床估,這世上最難降的妖魔是什么含滴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮丐巫,結(jié)果婚禮上谈况,老公的妹妹穿的比我還像新娘。我一直安慰自己递胧,他們只是感情好碑韵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著谓着,像睡著了一般泼诱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赊锚,一...
    開(kāi)封第一講書(shū)人閱讀 51,763評(píng)論 1 307
  • 那天治筒,我揣著相機(jī)與錄音屉栓,去河邊找鬼。 笑死耸袜,一個(gè)胖子當(dāng)著我的面吹牛友多,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播堤框,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼域滥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蜈抓?” 一聲冷哼從身側(cè)響起启绰,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沟使,沒(méi)想到半個(gè)月后委可,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腊嗡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年着倾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片燕少。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卡者,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出客们,到底是詐尸還是另有隱情崇决,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布镶摘,位于F島的核電站嗽桩,受9級(jí)特大地震影響岳守,放射性物質(zhì)發(fā)生泄漏凄敢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一湿痢、第九天 我趴在偏房一處隱蔽的房頂上張望涝缝。 院中可真熱鬧,春花似錦譬重、人聲如沸拒逮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)滩援。三九已至,卻和暖如春塔嬉,著一層夾襖步出監(jiān)牢的瞬間玩徊,已是汗流浹背租悄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恩袱,地道東北人泣棋。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像畔塔,于是被迫代替她去往敵國(guó)和親潭辈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355