關鍵詞: XMPP JID XML流 認證 加密
可擴展消息處理現(xiàn)場協(xié)議(eXtensible Messaging and Presence Protocol,XMPP)是一種基于可擴展標記語言(eXtensible Markup Language,XML)的近端串流式即時通信協(xié)議。它將現(xiàn)場和上下文敏感信息標記嵌入到XML結(jié)構(gòu)化數(shù)據(jù)中,使得人與人之間、應用系統(tǒng)之間以及人與應用系統(tǒng)之間能即時相互通信。XMPP協(xié)議已被批準為互聯(lián)網(wǎng)即時通信協(xié)議標準。
1 XMPP的地址和數(shù)據(jù)結(jié)構(gòu)
1.1 實體地址
XMPP整體框架如圖1所示。圖中,XMPP框架的各類實體(如XMPP客戶、服務器和網(wǎng)關等)的地址稱為甲吧地址(Jabber Identifier,JID)。JID惟一確定進行即時消息和在線狀態(tài)信息通信的獨立對象或?qū)嶓w,并可兼容其他即時通信系統(tǒng)(如MSN等)相應的實體標識及其在線狀態(tài)信息。其語法規(guī)則為:[節(jié)點″@″] 域名[″/″資源],其中各個域的長度不能超過1 023 字節(jié),總長度最大為3 071字節(jié)。
域名指定了實體連接的XMPP服務器。每個可用XMPP服務器都擁有一個完整域名,域名可在域名系統(tǒng)(DNS)中查找;節(jié)點可表示某用戶、一類應用或某項服務,所有節(jié)點都對應一個精確的域名;資源用來識別屬于用戶的特殊對象(如設備或位置),允許一個用戶同時以多個資源與同一XMPP服務器連接,如yb@sdpt.com/lab、yb@sdpt.com/chat。
1.2 XMPP的數(shù)據(jù)結(jié)構(gòu)
由于XMPP是基于XML的協(xié)議,因此用戶可根據(jù)自己的需要定義標記,表述幾乎任何一種結(jié)構(gòu)化數(shù)據(jù),并可方便地創(chuàng)建定制的應用或增加功能。
1.2.1 三個頂級XML元素
XMPP定義的3個關鍵頂級XML元素為<message/>、<presence/>和<iq/>(info/query),每個元素都可以通過屬性和名字空間包含大量數(shù)據(jù),其屬性和名字空間都是XMPP的組成部分。
<message/>元素用來包含2個XMPP實體間互相發(fā)送的消息內(nèi)容;<presence/>元素表示實體可用性信息,可用性信息有“可用”和“不可用”2種;<iq/>元素用來構(gòu)建2個實體間的會話,并且允許實體間來回傳送XML格式的請求和響應以便取得或設置公共的用戶信息,如名字等。
即時通信中名字沖突問題使用XML的命名空間特性來解決。XML命名空間定義了一種將XML中使用的元素和屬性與統(tǒng)一資源定位符(Uniform Resource Locator,URL)引用聯(lián)系起來對元素和屬性進行定義的方法。
1.2.2 XMPP的數(shù)據(jù)結(jié)構(gòu)
從結(jié)構(gòu)上看,XMPP有3種數(shù)據(jù):XML流、流認證和XML節(jié)。XML流是實體交換XML元素的容器,以<stream>開始,以</stream>結(jié)束,是通信雙方采用異步方式進行數(shù)據(jù)傳輸?shù)臉藴史椒ǎ谡麄€XMPP通信過程中處于最外層;XML節(jié)是實體通過XML流傳輸?shù)慕Y(jié)構(gòu)化信息單元,在XML流中以深度為1的子標記開頭,并以深度為1的子標記結(jié)束,這些標記為<message/>、<presence/>和<iq/>。XML節(jié)也可通過包含其他子元素來傳送結(jié)構(gòu)化信息,是實際需要交換的信息所在地;流認證是在XML流中有關協(xié)商傳輸層安全協(xié)議、簡單認證與安全層協(xié)議和服務器回撥認證協(xié)議完成通信認證、加密等目的的數(shù)據(jù)交互,是XMPP安全機制的重要組成部分。
XMPP為XML流扮演通用“傳輸層”的角色。XML流中包含傳輸?shù)恼J證信息和現(xiàn)場消息,XMPP能使數(shù)據(jù)高效路由至最合適的請求源,并最大限度地簡化客戶機上的實現(xiàn),使跨應用實時交流信息成為可能。
2 工作過程
(1)節(jié)點(如yb、pt)向本地服務器連接。
?、賆MPP用戶通過開啟一個從客戶端到服務器端的XML流,來申請一個在服務器上的Socket連接。
SEND: <stream:stream
to=′sdpt.com′
xmlns=′jabber:client′
xmlns:stream=′http://etherx.jabber.org/streams′>
?、诜掌魍ㄟ^開啟一個從服務器到客戶端的XML流進行回復。
RECV: <stream:stream
from=′sdpt.com′
id=′180763465′
xmlns=′jabber:client′
xmlns:stream=′http://etherx.jabber.org/streams′>
(2)節(jié)點向本地服務器申請登錄。
?、儆脩粼儐柕卿浄掌鲿r需提供的信息。
SEND: <iq id=′2′ type=′get′>
<query xmlns=′jabber:iq:auth′>
<username>yb</username>
</query>
</iq>
②服務器回應用戶,告知用戶登錄所需要的信息。
③用戶提供所需的信息。
④服務器響應一個空的類型為“result”的iq元素,表明登錄成功。
RECV:<iq id=′3′ type=′result′/>
⑤yb用戶發(fā)送當前狀態(tài)給服務器,表明其在線。
SEND: <presence>
<status>Online</status>
</presence>
(3)用戶獲得花名冊,好友增加一個聯(lián)系人(如yb獲知朋友sd在線)。
(4)用戶間發(fā)送消息(如yb向sd發(fā)送消息)。
用戶發(fā)送一條消息:
SEND: <message to′sd@jabber.org′>
<body>Where are you?</body>
</message>
服務器會根據(jù)XMPP用戶的會話信息加上一個源地址,這樣接收者收到消息時,消息中已經(jīng)包含了源地址。
(5)XMPP服務器根據(jù)目標JID中的域名查找、連接到目標服務器并進行認證(如sdpt.com使用DNS查找jabber.org,連接到jabber.org服務器上并進行認證)。
(6)XMPP服務器jabber.org證實sd連接到該服務器上,yb被授權(quán)與sd進行通信。
(7)數(shù)據(jù)在yb與sd間流動。
(8)用戶退出,退出時只需要關閉<stream>。
3 安全機制
3.1 簡單認證和安全層協(xié)商機制
簡單認證和安全層(Simple Authentication and Security Layer,SASL)可以為基于連接的協(xié)議加入認證機制,提供KERBEROS_V4、PLAIN和DIGEST-MD5等多種認證方法。每種認證機制包含認證機制名、認證過程初始化命令、認證控制命令、特定8位碼和解釋器等信息。
在認證過程中,認證服務器完成認證、授權(quán)標識傳送、簡單認證和安全層協(xié)商3個方面的工作。在XMPP中,SASL處理步驟如下(C:客戶端,S:SASL認證服務器):
(1)C、S之間建立連接。(2)S向C提供認證機制列表。(3)C在認證機制列表中選擇一種認證機制。(4)S向C詢問授權(quán)信息。(5)C向S提交授權(quán)信息。(6)S向C返回認證成功或失敗信息。
3.2 回撥認證
在通信過程中,2個XMPP服務器之間經(jīng)常需要通信,為避免利用服務器欺騙方式進行信息偽造,XMPP 采用了回撥認證機制?;負苷J證依靠DNS技術完成,利用回撥認證機制,一個服務器可以確認與自己建立連接的服務器是否經(jīng)過合法授權(quán),回撥認證過程為:(1)源服務器和接收服務器建立連接,并向接收服務器請求認證。接收服務器回應,并分配認證會話ID。(2)源服務器向接收服務器發(fā)送認證密鑰。(3)接收服務器與認證服務器建立連接。認證服務器同時為該認證會話分配一個驗證會話ID。(4)接收服務器把源服務器提交來的密鑰和驗證會話ID 發(fā)送給認證服務器,請求驗證。(5)認證服務器驗證密鑰,并給接收服務器返回認證結(jié)果。(6)接收服務器給源服務器返回認證結(jié)果。
3.3 加 密
雖然SASL提供了先進的認證機制,通信雙方必須經(jīng)過特定的授權(quán)認證才能進行正常通信,但是登錄信息一般都是密碼和用戶名等重要信息,它們大多采用明文方式傳送,因此很容易被竊聽。為解決該問題,XMPP采用基于傳輸層安全協(xié)議(Transport Layer Security,TLS)的“STARTTLS”擴展來為通信雙方提供機密性和數(shù)據(jù)完整性服務。TLS協(xié)議基于對稱密鑰算法和公鑰加密算法,能為各類客戶/服務器產(chǎn)品提供安全傳輸服務,現(xiàn)已成為保密通信的工業(yè)標準。
TLS協(xié)議框架主要有2個層次的協(xié)議:TLS握手協(xié)議和TLS記錄協(xié)議。TLS握手協(xié)議用來讓服務器與客戶在傳輸應用層數(shù)據(jù)之前交換TLS協(xié)議版本信息、協(xié)商加密算法、進行(相互)身份認證并交換密鑰。TLS記錄協(xié)議用來將應用層提供的信息進行分組、壓縮、數(shù)據(jù)完整性檢查和加密。數(shù)據(jù)完整性檢查通過比較傳輸前后使用安全散列函數(shù)(如SHA和MD5 等)計算出來的數(shù)據(jù)的MAC值是否一致來完成。數(shù)據(jù)加密采用對稱密碼算法(如R4和DES等)。對數(shù)據(jù)進行完整性檢查和加密的密鑰由TLS握手協(xié)議來協(xié)商。
XMPP中采用的STARTTLS擴展處理流程如下(C:客戶端,S:TLS服務器):
(1)C、S之間建立XML流會話連接。
(2)S 向C 發(fā)送STARTTLS擴展服務需求及支持的其他認證機制列表,代碼實例如下:
<stream:features>
<starttls xmlns=′urn:ietf:params:xml:ns:xmpp-tls′>
<required/>
</starttls>
<mechanisms xmlns=′urn:ietf:params:xml:ns:xmppsasl′>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
(3)C發(fā)送STARTTLS命令給S。
(4)C、S中TLS握手協(xié)議開始協(xié)商相關加密算法及密鑰。
(5)若TLS握手協(xié)議協(xié)商成功,則關閉當前XML流會話,C發(fā)起一個新的XML流會話,所有傳送的信息均被TLS記錄協(xié)議加密。TLS握手協(xié)議協(xié)商不成功則發(fā)出警告信息。
(6)S向C回復新XML流會話。
4 客戶端程序設計中的關鍵問題
由于網(wǎng)絡中已存在大量的XMPP服務器,在一般的應用開發(fā)中,只要設計自定功能的客戶端程序即可,并可以選用Smack庫來加速開發(fā)。
(1)創(chuàng)建一個XMPP連接。因為XMPP使用TCP協(xié)議,所以首先必須創(chuàng)建一個網(wǎng)絡連接,XMPPConnection就是Smack庫用來創(chuàng)建與XMPP服務器連接的類,創(chuàng)建一個XMPP連接的代碼如下:
XMPPConnection connection=new XMPPConnection(″jab-
ber.org″);
如要創(chuàng)建加密連接,可以使用SSLXMPPConnection類:
XMPPConnection connection=new SSLXMPPConnection(″jabber.org″);
(2)登錄。TCP連接創(chuàng)建后,需要使用用戶名和密碼登錄到XMPP服務器,登錄程序可以使用XMPPConnection.login(String username,String password)方法。登錄后就可以和其他人聊天。
connection.login(″yb″,″password″);//connection為已創(chuàng)建的XMPP連接,下同
connection.createChat(″yb@sdpt.com″).sendMessage
(″Hello!″);
(3)操作名冊。每個用戶都包括:一個XMPP地址(如“yb@sdpt.com”)、名稱或昵稱(如″yb″),及其所屬列表(如好友、同事等)。名冊能夠跟蹤好友或某用戶組是否在線及其狀態(tài)信息,登錄后,可以使用Roster類來取得好友或某用戶組的狀態(tài),代碼如下:
Roster roster=con.getRoster( );
for (Iterator i=roster.getEntries( );i.hasNext( ); ) {
System.out.println(i.next( ));}
名冊信息通常是隨時變化的,可能需要增加或刪除。要監(jiān)聽名單及其在線狀態(tài)的改變,可以使用RosterListener。
(4)發(fā)送和接收消息。發(fā)送接收消息可以使用Chat和GroupChat類。下面介紹如何使用Chat發(fā)送文本消息,GroupChat的使用方法類似。
Chat newChat=connection.createChat(″yb@sdpt.com″);//創(chuàng)建新Chat
newChat.sendMessage(″Hello!″);//發(fā)送消息″Hello!″
利用Chat.sendMessage( )方法可以方便地創(chuàng)建一個消息對象,它的參數(shù)就是消息內(nèi)容,執(zhí)行后消息會發(fā)送出去。Chat對象還能偵聽對方的回應,下面的代碼會將收到的任何消息返回給發(fā)送端。
Chat newChat=connection.createChat(″yb@sdpt.com″);
newMessage.setBody(″Hi, I′m waiting for you.″);
while (true) {
Message message=newChat.nextMessage( );//等待對方發(fā)送消息
newChat.sendMessage(message.getBody());//把對方
}//發(fā)送來的消息發(fā)回去
(5)修改狀態(tài)。要修改狀態(tài)可以用presence.Type.UNAV-ILABLE作為參數(shù)創(chuàng)建一個presence,狀態(tài)將改變?yōu)椴辉诰€狀態(tài)。以下代碼將修改為不在線狀態(tài),并告知溜冰去了:
Presence presence=new Presence(Presence.Type.UNAVAILABLE);
presence.setStatus(″Gone skating″);
5 結(jié)束語
目前,全球有20萬個即時通信平臺支持XMPP,有1 000萬人在使用。簡單的接口、開放的協(xié)議、互聯(lián)的架構(gòu)、權(quán)威的標準再加上堅實的用戶基礎是XMPP的優(yōu)勢。相信XMPP將為即時通信技術的運用提供更為廣闊的空間。
參考文獻
1 Peter S A.XMPP Core.RFC 3920,2004
2 Peter S A.XMPP Instant Messaging and Presence.RFC 3921,2004
3 Dierks T,Allen C,Treese W et al.The TLS Protocol Version 1.0.RFC 2246,1999
4 Myers J.Simple Authentication and Security Layer.RFC 2222,1997
5 Kaes C.Definition of Jabber Identifiers (JIDs).JEP 0029,2003
6 Mealling M.The IETF XML Registry.RFC 3688,2004