GLOOX 1.0---註冊模塊

改定履歷

2011-09-09---------------------新建文本文檔


引文:

調試GLOOX 1.0的註冊功能頗費了一些功夫。總體邏輯如GLOOX自帶的例子一樣是毫無疑問的,但是照搬例子又是不能完成註冊的,返回錯誤碼爲4------RegistrationBadRequest。筆者一開始在網上狂搜解決方案,資料少之又少,有建議重寫Client::handleNormalNode函數(目的是禁止SASL認證)的,有直接繼承Client重寫Client::handleNormalNode函數的,但都沒說到點子上。經過一段時間的研究,在GLOOX的maillist上得到啓發,順利完成註冊。現將解決方案記錄下來:


環境

客戶端:GLOOX1.0 VS2008

服務器:OPENFIRE 默認安裝


對於GLOOX自帶的註冊例子不能正常註冊的問題有人在郵件列表裏提出來。一個哥們這樣回答:

Ok, I've found what the problem was
In openFire server parameters, Anonymous Login => Disabled !!!

意思是要禁用openFire服務器裏的選項”註冊和登錄“的”匿名登錄“項

筆者按此說明禁用該選項,果然註冊成功。

這說明開始的註冊失敗是和匿名登錄有關係的。我們來看一下引用registration_expmple例子登錄失敗時的XML流:

S->C:服務器返回給客戶端支持的認證機制:

<stream:features xmlns:stream='http://etherx.jabber.org/streams'><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism><mechanism>CRAM-MD5</mechanism></mechanisms><compression xmlns='http://jabber.org/features/compress'><method>zlib</method></compression><auth xmlns='http://jabber.org/features/iq-auth'/><register xmlns='http://jabber.org/features/iq-register'/></stream:features>

從上面XML流中我們可以看到,默認openFire支持四種認證機制,分別是:DIGEST-MD5、PLAIN、ANONYMOUS、CRAM-MD5。然後我們看GLOOX客戶端的響應流:

C->S:客戶端返回選擇的認證方式:

<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>
可以看出,客戶端”無恥“的選擇了”匿名“--'ANONYMOUS'方式

接下來的流程就是客戶端”無恥“的選擇了以匿名的方式登錄了服務器,然後再發送註冊請求,請求如下:

<iq id='uid:4e69eccd:00006784' type='set' from='447e0585@zxl/447e0585' xmlns='jabber:client'><query xmlns='jabber:iq:register'><username>bbaxiao</username><password>123456</password><name>test2</name><email>[email protected]</email></query></iq>

我們看到,IQ節裏包含“form”屬性,即客戶端匿名身份標識。

注意,一個客戶端已經以一個身份(由服務器臨時分配的一個JID)登錄,建立了會話,在服務器上我們會看到這個會話,並且服務器發送心跳一直維護這個會話。這種情況下,這個客戶端再發送註冊請求(另一個身份)建立與服務器的連接是不被允許的。具體請參考XEP-0077(In-Band Registration):我們關注這兩段:

If the entity cancels its registration with its "home" server (i.e., the server at which it has maintained its XMPP account), then the entity SHOULD NOT include a 'from' or 'to' address in the remove request the server SHOULD then return a <not-authorized/> stream error and terminate all active sessions for the entity. The server SHOULD perform the remove based on the bare JID <[email protected]> associated with the current session or connection over which it received the remove request. If the server is an instant messaging and presence server that conforms to XMPP IM [8], the server SHOULD also cancel all existing presence subscriptions related to that entity (as stored in the entity's roster).

If the entity cancels its registration with a service other than its home server, its home server MUST stamp a 'from' address on the remove request, which in accordance with XMPP Core will be the entity's full JID <[email protected]/resource>. The service MUST perform the remove based on the bare JID <[email protected]> portion of the 'from' address.

意思是說註冊請求不能包含“from”屬性。

正常的註冊流如下:

<iq id='uid:4e69eccd:00003d6c' type='set' xmlns='jabber:client'><query xmlns='jabber:iq:register'><username>bbaxiao</username><password>123456</password><name>test2</name><email>[email protected]</email></query></iq>

---------------------------

綜上所述,解決方案如下:

一、關閉openFire的匿名登錄功能。^_^……

二、禁止GLOOX匿名認證功能。

file:client.cpp

fun: int Client::getSaslMechs( Tag* tag )

line:355

將355行註釋掉即可。
354:if( tag->hasChildWithCData( mech, "ANONYMOUS" ) )
355      //mechs |= SaslMechAnonymous;

重新編譯生成DLL即可。

三、手動設置GLOOX客戶端SASL認證機制

在調用j->connect()之前設置SASL認證機制,比如設置爲“DIGEST-MD5”

j->setSASLMechanisms(SaslMechDigestMd5);
這種方式的缺點是需要先確定服務器支持的認證機制。

四、根據XEP-0077所述,即使其名登錄,註冊流只要不帶“from”屬性應該也可以。所以我們要處理髮出的註冊流,去除“from”屬性重新發送註冊流即可。

發佈了31 篇原創文章 · 獲贊 2 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章