XMPP协议分析与应用探讨
摘 要: 分析了XMPP协议XMPP协议XMPP协议XMPP协议的地址规范和数据结构,讨论了XMPP协议的工作过程和安全机制,给出了XMPP客户端程序设计中要考虑的关键问题。关键词: XMPP JID XML流 认证 加密
可扩展消息处理现场协议(eXtensible Messaging and Presence Protocol,XMPP)是一种基于可扩展标记语言(eXtensible Markup Language,XML)的近端串流式即时通信协议。它将现场和上下文敏感信息标记嵌入到XML结构化数据中,使得人与人之间、应用系统之间以及人与应用系统之间能即时相互通信。XMPP协议已被批准为互联网即时通信协议标准。1 XMPP的地址和数据结构1.1 实体地址 XMPP整体框架。图中,XMPP框架的各类实体(如XMPP客户、服务器和网关等)的地址称为甲吧地址(Jabber Identifier,JID)。JID惟一确定进行即时消息和在线状态信息通信的独立对象或实体,并可兼容其他即时通信系统(如MSN等)相应的实体标识及其在线状态信息。其语法规则为:[节点″@″] 域名[″/″资源],其中各个域的长度不能超过1 023 字节,总长度最大为3 071字节。
域名指定了实体连接的XMPP服务器。每个可用XMPP服务器都拥有一个完整域名,域名可在域名系统(DNS)中查找;节点可表示某用户、一类应用或某项服务,所有节点都对应一个精确的域名;资源用来识别属于用户的特殊对象(如设备或位置),允许一个用户同时以多个资源与同一XMPP服务器连接,如yb@/lab、yb@/chat。1.2 XMPP的数据结构 由于XMPP是基于XML的协议,因此用户可根据自己的需要定义标记,表述几乎任何一种结构化数据,并可方便地创建定制的应用或增加功能。1.2.1 三个顶级XML元素 XMPP定义的3个关键顶级XML元素为<message/>、<presence/>和<iq/>(info/query),每个元素都可以通过属性和名字空间包含大量数据,其属性和名字空间都是XMPP的组成部分。<message/>元素用来包含2个XMPP实体间互相发送的消息内容;<presence/>元素表示实体可用性信息,可用性信息有“可用”和“不可用”2种;<iq/>元素用来构建2个实体间的会话,并且允许实体间来回传送XML格式的请求和响应以便取得或设置公共的用户信息,如名字等。 即时通信中名字冲突问题使用XML的命名空间特性来解决。XML命名空间定义了一种将XML中使用的元素和属性与统一资源定位符(Uniform Resource Locator,URL)引用联系起来对元素和属性进行定义的方法。1.2.2 XMPP的数据结构 从结构上看,XMPP有3种数据:XML流、流认证和XML节。XML流是实体交换XML元素的容器,以<stream>开始,以</stream>结
束,是通信双方采用异步方式进行数据传输的标准方法,在整个XMPP通信过程中处于最外层;XML节是实体通过XML流传输的结构化信息单元,在XML流中以深度为1的子标记开头,并以深度为1的子标记结束,这些标记为<message/>、<presence/>和<iq/>。XML节也可通过包含其他子元素来传送结构化信息,是实际需要交换的信息所在地;流认证是在XML流中有关协商传输层安全协议、简单认证与安全层协议和服务器回拨认证协议完成通信认证、加密等目的的数据交互,是XMPP安全机制的重要组成部分。 XMPP为XML流扮演通用“传输层”的角色。XML流中包含传输的认证信息和现场消息,XMPP能使数据高效路由至最合适的请求源,并最大限度地简化客户机上的实现,使跨应用实时交流信息成为可能。2 工作过程 (1)节点(如yb、pt)向本地服务器连接。 ①XMPP用户通过开启一个从客户端到服务器端的XML流,来申请一个在服务器上的Socket连接。SEND: <stream:stream to=′′ xmlns=′jabber:client′ xmlns:stream=′′ id=′180763465′ xmlns=′jabber:client′ xmlns:stream=′使用DNS查找,连接到服务器上并进行认证)。 (6)XMPP服务器证实sd连接到该服务器上,yb被授权与sd进行通信。 (7)数据在yb与sd间流动。 (8)用户退出,退出时只需要关闭<stream>。3 安全机制3.1 简单认证和安全层协商机制 简单认证和安全层(Simple Authentication and Security Layer,SASL)可以为基于连接的协议加入认证机制,提供KERBEROS_V4、PLAIN和DIGEST-MD5等多种认证方法。每种认证机制包含认证机制名、认证过程初始化命令、认证控制命令、特定8位码和解释器等信息。 在认证过程中,认证服务器完成认证、授权标识传送、简单认证和安全层协商3个方面的工作。在XMPP中,SASL处理步骤如下(C:客户端,S:SASL认证服务器): (1)C、S之间建立连接。(2)S向C提供认证机制列表。(3)C在认证机制列表中选择一种认证机制。(4)S向C询问授权信息。(5)C向S提交授权信息。(6)S向C返回认证成功或失败信息。3.2 回拨认证 在通信过程中,2个XMPP服务器之间经常需要通信,为避免利用服务器欺骗方式进行信息伪造,XMPP 采用了回拨认证机制。回拨认证依靠DNS技术完成,利用回拨认证机制,一个服务器可以确认与自己建立连接的服务器是否经过合法授权,回拨认证过程为:(1)源服务器和接收服务器建立连接,并向接收服务器请求认证。接收服务器回应,并分配认证会话ID。(2)源服务器向接收服务器发送认证密钥。(3)
接收服务器与认证服务器建立连接。认证服务器同时为该认证会话分配一个验证会话ID。(4)接收服务器把源服务器提交来的密钥和验证会话ID 发送给认证服务器,请求验证。(5)认证服务器验证密钥,并给接收服务器返回认证结果。(6)接收服务器给源服务器返回认证结果。3.3 加 密 虽然SASL提供了先进的认证机制,通信双方必须经过特定的授权认证才能进行正常通信,但是登录信息一般都是密码和用户名等重要信息,它们大多采用明文方式传送,因此很容易被窃听。为解决该问题,XMPP采用基于传输层安全协议(Transport Layer Security,TLS)的“STARTTLS”扩展来为通信双方提供机密性和数据完整性服务。TLS协议基于对称密钥算法和公钥加密算法,能为各类客户/服务器产品提供安全传输服务,现已成为保密通信的工业标准。 TLS协议框架主要有2个层次的协议:TLS握手协议和TLS记录协议。TLS握手协议用来让服务器与客户在传输应用层数据之前交换TLS协议版本信息、协商加密算法、进行(相互)身份认证并交换密钥。TLS记录协议用来将应用层提供的信息进行分组、压缩、数据完整性检查和加密。数据完整性检查通过比较传输前后使用安全散列函数(如SHA和MD5 等)计算出来的数据的MAC值是否一致来完成。数据加密采用对称密码算法(如R4和DES等)。对数据进行完整性检查和加密的密钥由TLS握手协议来协商。 XMPP中采用的STARTTLS扩展处理流程如下(C:客户端,S:TLS服务器): (1)C、S之间建立XML流会话连接。 (2)S 向C 发送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发送STARTTLS命令给S。 (4)C、S中TLS握手协议开始协商相关加密算法及密钥。 (5)若TLS握手协议协商成功,则关闭当前XML流会话,C发起一个新的XML流会话,所有传送的信息均被TLS记录协议加密。TLS握手协议协商不成功则发出警告信息。 (6)S向C回复新XML流会话。4 客户端程序设计中的关键问题 由于网络中已存在大量的XMPP服务器,在一般的应用开发中,只要设计自定功能的客户端程序即可,并可以选用Smack库来加速开发。 (1)创建一个XMPP连接。因为XMPP使用TCP协议,所以首先必须创建一个网络连接,XMPPConnection就是Smack库用来创建与XMPP服
务器连接的类,创建一个XMPP连接的代码如下: XMPPConnection connection=new XMPPConnection(″″); 如要创建加密连接,可以使用SSLXMPPConnection类: XMPPConnection connection=new SSLXMPPConnection(″″); (2)登录。TCP连接创建后,需要使用用户名和密码登录到XMPP服务器,登录程序可以使用XMPPConnection.login(String username,String password)方法。登录后就可以和其他人聊天。connection.login(″yb″,″password″);//connection为已创建的XMPP连接,下同 connection.createChat(″yb@″).sendMessage(″Hello!″); (3)操作名册。每个用户都包括:一个XMPP地址(如“yb@”)、名称或昵称(如″yb″),及其所属列表(如好友、同事等)。名册能够跟踪好友或某用户组是否在线及其状态信息,登录后,可以使用Roster类来取得好友或某用户组的状态,代码如下: Roster roster=con.getRoster( ); for (Iterator i=roster.getEntries( );i.hasNext( ); ) { System.out.println(i.next( ));} 名册信息通常是随时变化的,可能需要增加或删除。要监听名单及其在线状态的改变,可以使用RosterListener。 (4)发送和接收消息。发送接收消息可以使用Chat和GroupChat类。下面介绍如何使用Chat发送文本消息,GroupChat的使用方法类似。 Chat newChat=connection.createChat(″yb@″);//创建新Chat newChat.sendMessage(″Hello!″);//发送消息″Hello!″ 利用Chat.sendMessage( )方法可以方便地创建一个消息对象,它的参数就是消息内容,执行后消息会发送出去。Chat对象还能侦听对方的回应,下面的代码会将收到的任何消息返回给发送端。 Chat newChat=connection.createChat(″yb@″); newMessage.setBody(″Hi, I′m waiting for you.″); while (true) { Message message=newChat.nextMessage( );//等待对方发送消息 newChat.sendMessage(message.getBody());//把对方 }//发送来的消息发回去 (5)修改状态。要修改状态可以用presence.Type.UNAV-ILABLE作为参数创建一个presence,状态将改变为不在线状态。以下代码将修改为不在线状态,并告知溜冰去了: Presence presence=new Presence(Presence.Type.UNAVAILABLE); presence.setStatus(″Gone skating″);5 结束语 目前,全球有20万个即时通信平台支持XMPP,有1 000万人在使用。简单的接口、开放的协议、互联的架构、权威的标准再加上坚实的用户基础是XMPP的优势。相信XMPP将为即时通信技术的运用提供更为广阔的空间。