XEP-0114
(→处理流程) |
|||
(未显示1个用户的10个中间版本) | |||
第21行: | 第21行: | ||
注意:这个历史的规范提供了目前在Jabber/XMPP社区中使用的一个协议.本文不是XMPP标准化基金会标准跟踪过程中的标准跟踪协议,不过,将来它可能被转化为标准跟踪,也可能被一个更新的协议取代。 | 注意:这个历史的规范提供了目前在Jabber/XMPP社区中使用的一个协议.本文不是XMPP标准化基金会标准跟踪过程中的标准跟踪协议,不过,将来它可能被转化为标准跟踪,也可能被一个更新的协议取代。 | ||
+ | |||
+ | ==简介== | ||
+ | 很久之前jabber网络就包含了使受信任的外部组件能够连接到jabber服务器的协议框架。虽然这些组件协议很简单而且可能在某个时刻被更全面的组件协议替代,但是现有的协议文档还是对开发组件和服务器很有帮助。本规范提供了这样的文档。 | ||
+ | |||
+ | ==概念== | ||
+ | 传统上有两种完全不同的服务器端组件类型:内部组件(即在过去特别是jabberd[1]那样, 利用服务器的内部API提供服务)和外部组件(组件在一个协议框架上与服务器联系,因此不依赖任何特定的服务器实现). 目前使用的组件协议框架使得一个外部组件能够连接到一个服务器(通过适当的配置和验证)并能通过服务器发送和接收XML节。有两种连接方法:“accept”和“connect”。使用“accept”方法时,服务器等待并接受被组件初始化的连接。使用“connect”方法时,由服务器初始化到组件的连接。目前“accept”方法最常用,但是这两者方法在文档都会被提及。(从前还有一种针对外部组件的连接方法“execute”,当时已经过时,因此在文档中不会提及。) 外部组件被称作“trusted”因为使用证书包含一个共享密钥与服务器进行认证,这个被服务器和组件使用的密钥通常在配置文件中指定,但是 可以运行时通过命令行提供或从数据库提取。外部组件是被普遍信任的,能做一些客户端不能做的事情,,如写‘from’地址为服务器的域名(S).也有些服务器允许组件使用内部协议发送数据包(例如,jabberd 1.x系列中的<log/>和<xdb/>数据包),但是这些内部协议超出了本文的范围。 | ||
+ | |||
+ | ==处理流程== | ||
+ | jabber : component : * 命名空间与 jabber :client 和 jabber :server 命名空间的主要不同在于认证。外部组件不使用过时的 Non-SASL认证协议(例如: jabber : iq :auth 命名空间),也还没有使用在XMPP核心中定义的SASL认证(虽然组件协议未来可能会使用SASL)。相反,他们使用一种特殊的<handshake/>元素的XML字符数据指定为组件与服务器的会话凭证。使用 jabber:component:accept的流协商认证处理流程如下: | ||
+ | |||
+ | '''例1.组件发送流头到服务器''' | ||
+ | |||
+ | <source lang="xml"> | ||
+ | <stream:stream | ||
+ | xmlns='jabber:component:accept' | ||
+ | xmlns:stream='http://etherx.jabber.org/streams' | ||
+ | to='plays.shakespeare.lit'> | ||
+ | </source> | ||
+ | 注意:在'jabber:component:accept'命名空间,'to'地址的值是组建的名字,不是服务器的名字; 这使得服务器能够确认该名称对应的提供服务的组件(例如,基于服务器的配置或其他特定的实现机制)。如果是这样,服务器必须(MUST)响应一个流头(stream header)。 | ||
+ | |||
+ | |||
+ | '''例2,服务响应流头,包含一个流ID''' | ||
+ | |||
+ | <source lang="xml"> | ||
+ | <stream:stream | ||
+ | xmlns:stream='http://etherx.jabber.org/streams' | ||
+ | xmlns='jabber:component:accept' | ||
+ | from='plays.shakespeare.lit' | ||
+ | id='3BF96D32'> | ||
+ | </source> | ||
+ | |||
+ | 如果服务器在流头(stream header)的‘to’属性中的组件名没有提供服务,服务器必须(MUST)返回一个错误流(例如,<conflict/> 或 <host-unknown/>).如果服务器不识别或支持流头(stream header)指定的命名空间(例如,不支持‘jabber:component:accept’命名空间中的流),服务器必须(MUST)返回一个<invalid-namespace/>错误流。对于与流头(stream header)相关的所有错误,服务器必须(MUST)按照XMPP核心的4.7.1节中规定的返回一个开放的流标签,错误流元素,和流关闭标签,而不仅仅是一个流错误元素(详细信息参看RFC 3920)。 | ||
+ | |||
+ | 当收到服务器发回的流头(stream header),组件必须(MUST)发送带上适当内容的<handshake/>元素。 | ||
+ | |||
+ | '''例3,组件发送handshake元素''' | ||
+ | |||
+ | <source lang="xml"> | ||
+ | <handshake>aaee83c26aeeafcbabeabfcbcd50df997e0a2a1e</handshake> | ||
+ | </source> | ||
+ | |||
+ | handshake元素中带的XML字符串信息根据以下算法生成: | ||
+ | |||
+ | 1.将流ID与从服务器收到的共享密钥连接(如果有必要,字符串映射到预定义的XML实体必须根据XML规范4.6节中的规则进行转义,并且任何非ACSII字符必须根据XMPP核心中指定的XML流编码规则进行编码,例如RFC3269中指定的UTF-8). | ||
+ | |||
+ | 2.根据连接的字符串使用SHA1算法进行哈希,例如,SHA1(concat(sid,password)). | ||
+ | |||
+ | 3.确保哈希输出16进制格式,而不是二进制或Base64. | ||
+ | |||
+ | 4.将哈希输出都转换为小写. | ||
+ | |||
+ | 如果由发起人提供的凭据无效,接收者必须(MUST)关闭流和底层TCP连接,并应该(SHOULD)返回<not-authorized/>错误流。 | ||
+ | |||
+ | |||
+ | 如果凭据被接受,接收应用(在这里是服务器)必须(MUST)返回一个空的<handshake/>元素。 | ||
+ | |||
+ | '''例4,服务器发送空的handshake元素来确认成功''' | ||
+ | |||
+ | <source lang="xml"> | ||
+ | <handshake/> | ||
+ | </source> | ||
+ | |||
+ | 一旦通过验证,该组件可以通过服务器发送节和接收服务器发送的节。发送到服务器的所有XML节必须(MUST)拥有一个‘from’属性和一个‘to’属性,在‘jabber:server’命名空间。‘from’属性包含的JID中的域名部分必须(MUST)与自建的主机名匹配。不管怎样,这是对‘from’地址唯一的限制,组件可能(MAY)用其所在主机的任何用户发送XML节。 | ||
+ | |||
+ | ==安全事项== | ||
+ | 鉴于组件主机上的任何用户写的‘from’地址都被信任,服务器管理员应该(SHOULD)确保组件软件值得信任。 | ||
+ | |||
+ | ==IANA事项== | ||
+ | |||
+ | 本文档与互联网编号分配授权机构(IANA)无关 | ||
+ | |||
+ | |||
+ | ==XMPP注册事项== | ||
+ | XMPP注册包含‘jabber:component:accept’和‘jabber:component:connect’在其注册的协议命名空间。 | ||
+ | |||
+ | ==XML Schemas== | ||
+ | ====jabber:commponent:accept==== | ||
+ | <source lang="xml"> | ||
+ | <?xml version='1.0' encoding='UTF-8'?> | ||
+ | |||
+ | <xs:schema | ||
+ | xmlns:xs='http://www.w3.org/2001/XMLSchema' | ||
+ | xmlns:xml='http://www.w3.org/XML/1998/namespace' | ||
+ | targetNamespace='jabber:component:accept' | ||
+ | xmlns='jabber:component:accept' | ||
+ | elementFormDefault='qualified'> | ||
+ | |||
+ | <xs:annotation> | ||
+ | <xs:documentation> | ||
+ | The protocol documented by this schema is defined in | ||
+ | XEP-0114: http://xmpp.org/extensions/xep-0114.html | ||
+ | </xs:documentation> | ||
+ | </xs:annotation> | ||
+ | |||
+ | <xs:import namespace='urn:ietf:params:xml:ns:xmpp-streams' | ||
+ | schemaLocation='http://xmpp.org/schemas/streamerror.xsd'/> | ||
+ | |||
+ | <xs:import namespace='http://www.w3.org/XML/1998/namespace' | ||
+ | schemaLocation='http://www.w3.org/2001/03/xml.xsd'/> | ||
+ | |||
+ | <xs:element name='handshake' type='xs:string'/> | ||
+ | |||
+ | <xs:element name='message'> | ||
+ | <xs:complexType> | ||
+ | <xs:sequence> | ||
+ | <xs:choice minOccurs='0' maxOccurs='unbounded'> | ||
+ | <xs:element ref='subject'/> | ||
+ | <xs:element ref='body'/> | ||
+ | <xs:element ref='thread'/> | ||
+ | </xs:choice> | ||
+ | <xs:any namespace='##other' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='unbounded'/> | ||
+ | <xs:element ref='error' | ||
+ | minOccurs='0'/> | ||
+ | </xs:sequence> | ||
+ | <xs:attribute name='from' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='id' | ||
+ | type='xs:NMTOKEN' | ||
+ | use='optional'/> | ||
+ | <xs:attribute name='to' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='type' use='optional' default='normal'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='chat'/> | ||
+ | <xs:enumeration value='error'/> | ||
+ | <xs:enumeration value='groupchat'/> | ||
+ | <xs:enumeration value='headline'/> | ||
+ | <xs:enumeration value='normal'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:attribute> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='body'> | ||
+ | <xs:complexType> | ||
+ | <xs:simpleContent> | ||
+ | <xs:extension base='xs:string'> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:extension> | ||
+ | </xs:simpleContent> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='subject'> | ||
+ | <xs:complexType> | ||
+ | <xs:simpleContent> | ||
+ | <xs:extension base='xs:string'> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:extension> | ||
+ | </xs:simpleContent> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='thread' type='xs:NMTOKEN'/> | ||
+ | |||
+ | <xs:element name='presence'> | ||
+ | <xs:complexType> | ||
+ | <xs:sequence> | ||
+ | <xs:choice minOccurs='0' maxOccurs='unbounded'> | ||
+ | <xs:element ref='show'/> | ||
+ | <xs:element ref='status'/> | ||
+ | <xs:element ref='priority'/> | ||
+ | </xs:choice> | ||
+ | <xs:any namespace='##other' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='unbounded'/> | ||
+ | <xs:element ref='error' | ||
+ | minOccurs='0'/> | ||
+ | </xs:sequence> | ||
+ | <xs:attribute name='from' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='id' | ||
+ | type='xs:NMTOKEN' | ||
+ | use='optional'/> | ||
+ | <xs:attribute name='to' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='type' use='optional'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='subscribe'/> | ||
+ | <xs:enumeration value='subscribed'/> | ||
+ | <xs:enumeration value='unsubscribe'/> | ||
+ | <xs:enumeration value='unsubscribed'/> | ||
+ | <xs:enumeration value='unavailable'/> | ||
+ | <xs:enumeration value='probe'/> | ||
+ | <xs:enumeration value='error'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:attribute> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='show'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='away'/> | ||
+ | <xs:enumeration value='chat'/> | ||
+ | <xs:enumeration value='dnd'/> | ||
+ | <xs:enumeration value='xa'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='status'> | ||
+ | <xs:complexType> | ||
+ | <xs:simpleContent> | ||
+ | <xs:extension base='xs:string'> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:extension> | ||
+ | </xs:simpleContent> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='priority' type='xs:byte'/> | ||
+ | |||
+ | <xs:element name='iq'> | ||
+ | <xs:complexType> | ||
+ | <xs:sequence> | ||
+ | <xs:any namespace='##other' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='1'/> | ||
+ | <xs:element ref='error' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='1'/> | ||
+ | </xs:sequence> | ||
+ | <xs:attribute name='from' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='id' | ||
+ | type='xs:NMTOKEN' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='to' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='type' use='required'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='get'/> | ||
+ | <xs:enumeration value='set'/> | ||
+ | <xs:enumeration value='result'/> | ||
+ | <xs:enumeration value='error'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:attribute> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='error'> | ||
+ | <xs:complexType> | ||
+ | <xs:sequence xmlns:err='urn:ietf:params:xml:ns:xmpp-streams'> | ||
+ | <xs:group ref='err:stanzaErrorGroup'/> | ||
+ | <xs:element ref='err:text' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='1'/> | ||
+ | </xs:sequence> | ||
+ | <xs:attribute name='code' type='xs:byte' use='optional'/> | ||
+ | <xs:attribute name='type' use='required'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='cancel'/> | ||
+ | <xs:enumeration value='continue'/> | ||
+ | <xs:enumeration value='modify'/> | ||
+ | <xs:enumeration value='auth'/> | ||
+ | <xs:enumeration value='wait'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:attribute> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | </xs:schema> | ||
+ | |||
+ | </source> | ||
+ | |||
+ | |||
+ | ====jabber:component:connect==== | ||
+ | <source lang="xml"> | ||
+ | <?xml version='1.0' encoding='UTF-8'?> | ||
+ | |||
+ | <xs:schema | ||
+ | xmlns:xs='http://www.w3.org/2001/XMLSchema' | ||
+ | xmlns:xml='http://www.w3.org/XML/1998/namespace' | ||
+ | targetNamespace='jabber:component:connect' | ||
+ | xmlns='jabber:component:connect' | ||
+ | elementFormDefault='qualified'> | ||
+ | |||
+ | <xs:annotation> | ||
+ | <xs:documentation> | ||
+ | The protocol documented by this schema is defined in | ||
+ | XEP-0114: http://xmpp.org/extensions/xep-0114.html | ||
+ | </xs:documentation> | ||
+ | </xs:annotation> | ||
+ | |||
+ | <xs:import namespace='urn:ietf:params:xml:ns:xmpp-streams' | ||
+ | schemaLocation='http://xmpp.org/schemas/streamerror.xsd'/> | ||
+ | |||
+ | <xs:import namespace='http://www.w3.org/XML/1998/namespace' | ||
+ | schemaLocation='http://www.w3.org/2001/03/xml.xsd'/> | ||
+ | |||
+ | <xs:element name='handshake' type='xs:string'/> | ||
+ | |||
+ | <xs:element name='message'> | ||
+ | <xs:complexType> | ||
+ | <xs:sequence> | ||
+ | <xs:choice minOccurs='0' maxOccurs='unbounded'> | ||
+ | <xs:element ref='subject'/> | ||
+ | <xs:element ref='body'/> | ||
+ | <xs:element ref='thread'/> | ||
+ | </xs:choice> | ||
+ | <xs:any namespace='##other' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='unbounded'/> | ||
+ | <xs:element ref='error' | ||
+ | minOccurs='0'/> | ||
+ | </xs:sequence> | ||
+ | <xs:attribute name='from' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='id' | ||
+ | type='xs:NMTOKEN' | ||
+ | use='optional'/> | ||
+ | <xs:attribute name='to' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='type' use='optional' default='normal'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='chat'/> | ||
+ | <xs:enumeration value='error'/> | ||
+ | <xs:enumeration value='groupchat'/> | ||
+ | <xs:enumeration value='headline'/> | ||
+ | <xs:enumeration value='normal'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:attribute> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='body'> | ||
+ | <xs:complexType> | ||
+ | <xs:simpleContent> | ||
+ | <xs:extension base='xs:string'> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:extension> | ||
+ | </xs:simpleContent> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='subject'> | ||
+ | <xs:complexType> | ||
+ | <xs:simpleContent> | ||
+ | <xs:extension base='xs:string'> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:extension> | ||
+ | </xs:simpleContent> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='thread' type='xs:NMTOKEN'/> | ||
+ | |||
+ | <xs:element name='presence'> | ||
+ | <xs:complexType> | ||
+ | <xs:sequence> | ||
+ | <xs:choice minOccurs='0' maxOccurs='unbounded'> | ||
+ | <xs:element ref='show'/> | ||
+ | <xs:element ref='status'/> | ||
+ | <xs:element ref='priority'/> | ||
+ | </xs:choice> | ||
+ | <xs:any namespace='##other' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='unbounded'/> | ||
+ | <xs:element ref='error' | ||
+ | minOccurs='0'/> | ||
+ | </xs:sequence> | ||
+ | <xs:attribute name='from' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='id' | ||
+ | type='xs:NMTOKEN' | ||
+ | use='optional'/> | ||
+ | <xs:attribute name='to' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='type' use='optional'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='subscribe'/> | ||
+ | <xs:enumeration value='subscribed'/> | ||
+ | <xs:enumeration value='unsubscribe'/> | ||
+ | <xs:enumeration value='unsubscribed'/> | ||
+ | <xs:enumeration value='unavailable'/> | ||
+ | <xs:enumeration value='probe'/> | ||
+ | <xs:enumeration value='error'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:attribute> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='show'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='away'/> | ||
+ | <xs:enumeration value='chat'/> | ||
+ | <xs:enumeration value='dnd'/> | ||
+ | <xs:enumeration value='xa'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='status'> | ||
+ | <xs:complexType> | ||
+ | <xs:simpleContent> | ||
+ | <xs:extension base='xs:string'> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:extension> | ||
+ | </xs:simpleContent> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='priority' type='xs:byte'/> | ||
+ | |||
+ | <xs:element name='iq'> | ||
+ | <xs:complexType> | ||
+ | <xs:sequence> | ||
+ | <xs:any namespace='##other' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='1'/> | ||
+ | <xs:element ref='error' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='1'/> | ||
+ | </xs:sequence> | ||
+ | <xs:attribute name='from' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='id' | ||
+ | type='xs:NMTOKEN' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='to' | ||
+ | type='xs:string' | ||
+ | use='required'/> | ||
+ | <xs:attribute name='type' use='required'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='get'/> | ||
+ | <xs:enumeration value='set'/> | ||
+ | <xs:enumeration value='result'/> | ||
+ | <xs:enumeration value='error'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:attribute> | ||
+ | <xs:attribute ref='xml:lang' use='optional'/> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | <xs:element name='error'> | ||
+ | <xs:complexType> | ||
+ | <xs:sequence xmlns:err='urn:ietf:params:xml:ns:xmpp-streams'> | ||
+ | <xs:group ref='err:streamErrorGroup'/> | ||
+ | <xs:element ref='err:text' | ||
+ | minOccurs='0' | ||
+ | maxOccurs='1'/> | ||
+ | </xs:sequence> | ||
+ | <xs:attribute name='code' type='xs:byte' use='optional'/> | ||
+ | <xs:attribute name='type' use='required'> | ||
+ | <xs:simpleType> | ||
+ | <xs:restriction base='xs:NCName'> | ||
+ | <xs:enumeration value='cancel'/> | ||
+ | <xs:enumeration value='continue'/> | ||
+ | <xs:enumeration value='modify'/> | ||
+ | <xs:enumeration value='auth'/> | ||
+ | <xs:enumeration value='wait'/> | ||
+ | </xs:restriction> | ||
+ | </xs:simpleType> | ||
+ | </xs:attribute> | ||
+ | </xs:complexType> | ||
+ | </xs:element> | ||
+ | |||
+ | </xs:schema> | ||
+ | |||
+ | </source> |
2010年9月19日 (日) 07:13的最后版本
本文的英文原文来自[1]
XEP-0114: Jabber组件协议
摘要:本文档定义了jabber网络上的Servers与外部组件之间的通讯。
作者: Peter Saint-Andre
版权: © 1999 - 2010 XMPP标准化基金会(XSF). 参见法律通告.
现状: 活跃
类型: 历史
版本: 1.5
最后更新: 2005-03-03
注意:这个历史的规范提供了目前在Jabber/XMPP社区中使用的一个协议.本文不是XMPP标准化基金会标准跟踪过程中的标准跟踪协议,不过,将来它可能被转化为标准跟踪,也可能被一个更新的协议取代。
目录 |
简介
很久之前jabber网络就包含了使受信任的外部组件能够连接到jabber服务器的协议框架。虽然这些组件协议很简单而且可能在某个时刻被更全面的组件协议替代,但是现有的协议文档还是对开发组件和服务器很有帮助。本规范提供了这样的文档。
概念
传统上有两种完全不同的服务器端组件类型:内部组件(即在过去特别是jabberd[1]那样, 利用服务器的内部API提供服务)和外部组件(组件在一个协议框架上与服务器联系,因此不依赖任何特定的服务器实现). 目前使用的组件协议框架使得一个外部组件能够连接到一个服务器(通过适当的配置和验证)并能通过服务器发送和接收XML节。有两种连接方法:“accept”和“connect”。使用“accept”方法时,服务器等待并接受被组件初始化的连接。使用“connect”方法时,由服务器初始化到组件的连接。目前“accept”方法最常用,但是这两者方法在文档都会被提及。(从前还有一种针对外部组件的连接方法“execute”,当时已经过时,因此在文档中不会提及。) 外部组件被称作“trusted”因为使用证书包含一个共享密钥与服务器进行认证,这个被服务器和组件使用的密钥通常在配置文件中指定,但是 可以运行时通过命令行提供或从数据库提取。外部组件是被普遍信任的,能做一些客户端不能做的事情,,如写‘from’地址为服务器的域名(S).也有些服务器允许组件使用内部协议发送数据包(例如,jabberd 1.x系列中的<log/>和<xdb/>数据包),但是这些内部协议超出了本文的范围。
处理流程
jabber : component : * 命名空间与 jabber :client 和 jabber :server 命名空间的主要不同在于认证。外部组件不使用过时的 Non-SASL认证协议(例如: jabber : iq :auth 命名空间),也还没有使用在XMPP核心中定义的SASL认证(虽然组件协议未来可能会使用SASL)。相反,他们使用一种特殊的<handshake/>元素的XML字符数据指定为组件与服务器的会话凭证。使用 jabber:component:accept的流协商认证处理流程如下:
例1.组件发送流头到服务器
<stream:stream xmlns='jabber:component:accept' xmlns:stream='http://etherx.jabber.org/streams' to='plays.shakespeare.lit'>
注意:在'jabber:component:accept'命名空间,'to'地址的值是组建的名字,不是服务器的名字; 这使得服务器能够确认该名称对应的提供服务的组件(例如,基于服务器的配置或其他特定的实现机制)。如果是这样,服务器必须(MUST)响应一个流头(stream header)。
例2,服务响应流头,包含一个流ID
<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' from='plays.shakespeare.lit' id='3BF96D32'>
如果服务器在流头(stream header)的‘to’属性中的组件名没有提供服务,服务器必须(MUST)返回一个错误流(例如,<conflict/> 或 <host-unknown/>).如果服务器不识别或支持流头(stream header)指定的命名空间(例如,不支持‘jabber:component:accept’命名空间中的流),服务器必须(MUST)返回一个<invalid-namespace/>错误流。对于与流头(stream header)相关的所有错误,服务器必须(MUST)按照XMPP核心的4.7.1节中规定的返回一个开放的流标签,错误流元素,和流关闭标签,而不仅仅是一个流错误元素(详细信息参看RFC 3920)。
当收到服务器发回的流头(stream header),组件必须(MUST)发送带上适当内容的<handshake/>元素。
例3,组件发送handshake元素
<handshake>aaee83c26aeeafcbabeabfcbcd50df997e0a2a1e</handshake>
handshake元素中带的XML字符串信息根据以下算法生成:
1.将流ID与从服务器收到的共享密钥连接(如果有必要,字符串映射到预定义的XML实体必须根据XML规范4.6节中的规则进行转义,并且任何非ACSII字符必须根据XMPP核心中指定的XML流编码规则进行编码,例如RFC3269中指定的UTF-8).
2.根据连接的字符串使用SHA1算法进行哈希,例如,SHA1(concat(sid,password)).
3.确保哈希输出16进制格式,而不是二进制或Base64.
4.将哈希输出都转换为小写.
如果由发起人提供的凭据无效,接收者必须(MUST)关闭流和底层TCP连接,并应该(SHOULD)返回<not-authorized/>错误流。
如果凭据被接受,接收应用(在这里是服务器)必须(MUST)返回一个空的<handshake/>元素。
例4,服务器发送空的handshake元素来确认成功
<handshake/>
一旦通过验证,该组件可以通过服务器发送节和接收服务器发送的节。发送到服务器的所有XML节必须(MUST)拥有一个‘from’属性和一个‘to’属性,在‘jabber:server’命名空间。‘from’属性包含的JID中的域名部分必须(MUST)与自建的主机名匹配。不管怎样,这是对‘from’地址唯一的限制,组件可能(MAY)用其所在主机的任何用户发送XML节。
安全事项
鉴于组件主机上的任何用户写的‘from’地址都被信任,服务器管理员应该(SHOULD)确保组件软件值得信任。
IANA事项
本文档与互联网编号分配授权机构(IANA)无关
XMPP注册事项
XMPP注册包含‘jabber:component:accept’和‘jabber:component:connect’在其注册的协议命名空间。
XML Schemas
jabber:commponent:accept
<?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:xml='http://www.w3.org/XML/1998/namespace' targetNamespace='jabber:component:accept' xmlns='jabber:component:accept' elementFormDefault='qualified'> <xs:annotation> <xs:documentation> The protocol documented by this schema is defined in XEP-0114: http://xmpp.org/extensions/xep-0114.html </xs:documentation> </xs:annotation> <xs:import namespace='urn:ietf:params:xml:ns:xmpp-streams' schemaLocation='http://xmpp.org/schemas/streamerror.xsd'/> <xs:import namespace='http://www.w3.org/XML/1998/namespace' schemaLocation='http://www.w3.org/2001/03/xml.xsd'/> <xs:element name='handshake' type='xs:string'/> <xs:element name='message'> <xs:complexType> <xs:sequence> <xs:choice minOccurs='0' maxOccurs='unbounded'> <xs:element ref='subject'/> <xs:element ref='body'/> <xs:element ref='thread'/> </xs:choice> <xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/> <xs:element ref='error' minOccurs='0'/> </xs:sequence> <xs:attribute name='from' type='xs:string' use='required'/> <xs:attribute name='id' type='xs:NMTOKEN' use='optional'/> <xs:attribute name='to' type='xs:string' use='required'/> <xs:attribute name='type' use='optional' default='normal'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='chat'/> <xs:enumeration value='error'/> <xs:enumeration value='groupchat'/> <xs:enumeration value='headline'/> <xs:enumeration value='normal'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute ref='xml:lang' use='optional'/> </xs:complexType> </xs:element> <xs:element name='body'> <xs:complexType> <xs:simpleContent> <xs:extension base='xs:string'> <xs:attribute ref='xml:lang' use='optional'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name='subject'> <xs:complexType> <xs:simpleContent> <xs:extension base='xs:string'> <xs:attribute ref='xml:lang' use='optional'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name='thread' type='xs:NMTOKEN'/> <xs:element name='presence'> <xs:complexType> <xs:sequence> <xs:choice minOccurs='0' maxOccurs='unbounded'> <xs:element ref='show'/> <xs:element ref='status'/> <xs:element ref='priority'/> </xs:choice> <xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/> <xs:element ref='error' minOccurs='0'/> </xs:sequence> <xs:attribute name='from' type='xs:string' use='required'/> <xs:attribute name='id' type='xs:NMTOKEN' use='optional'/> <xs:attribute name='to' type='xs:string' use='required'/> <xs:attribute name='type' use='optional'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='subscribe'/> <xs:enumeration value='subscribed'/> <xs:enumeration value='unsubscribe'/> <xs:enumeration value='unsubscribed'/> <xs:enumeration value='unavailable'/> <xs:enumeration value='probe'/> <xs:enumeration value='error'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute ref='xml:lang' use='optional'/> </xs:complexType> </xs:element> <xs:element name='show'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='away'/> <xs:enumeration value='chat'/> <xs:enumeration value='dnd'/> <xs:enumeration value='xa'/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name='status'> <xs:complexType> <xs:simpleContent> <xs:extension base='xs:string'> <xs:attribute ref='xml:lang' use='optional'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name='priority' type='xs:byte'/> <xs:element name='iq'> <xs:complexType> <xs:sequence> <xs:any namespace='##other' minOccurs='0' maxOccurs='1'/> <xs:element ref='error' minOccurs='0' maxOccurs='1'/> </xs:sequence> <xs:attribute name='from' type='xs:string' use='required'/> <xs:attribute name='id' type='xs:NMTOKEN' use='required'/> <xs:attribute name='to' type='xs:string' use='required'/> <xs:attribute name='type' use='required'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='get'/> <xs:enumeration value='set'/> <xs:enumeration value='result'/> <xs:enumeration value='error'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute ref='xml:lang' use='optional'/> </xs:complexType> </xs:element> <xs:element name='error'> <xs:complexType> <xs:sequence xmlns:err='urn:ietf:params:xml:ns:xmpp-streams'> <xs:group ref='err:stanzaErrorGroup'/> <xs:element ref='err:text' minOccurs='0' maxOccurs='1'/> </xs:sequence> <xs:attribute name='code' type='xs:byte' use='optional'/> <xs:attribute name='type' use='required'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='cancel'/> <xs:enumeration value='continue'/> <xs:enumeration value='modify'/> <xs:enumeration value='auth'/> <xs:enumeration value='wait'/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> </xs:schema>
jabber:component:connect
<?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:xml='http://www.w3.org/XML/1998/namespace' targetNamespace='jabber:component:connect' xmlns='jabber:component:connect' elementFormDefault='qualified'> <xs:annotation> <xs:documentation> The protocol documented by this schema is defined in XEP-0114: http://xmpp.org/extensions/xep-0114.html </xs:documentation> </xs:annotation> <xs:import namespace='urn:ietf:params:xml:ns:xmpp-streams' schemaLocation='http://xmpp.org/schemas/streamerror.xsd'/> <xs:import namespace='http://www.w3.org/XML/1998/namespace' schemaLocation='http://www.w3.org/2001/03/xml.xsd'/> <xs:element name='handshake' type='xs:string'/> <xs:element name='message'> <xs:complexType> <xs:sequence> <xs:choice minOccurs='0' maxOccurs='unbounded'> <xs:element ref='subject'/> <xs:element ref='body'/> <xs:element ref='thread'/> </xs:choice> <xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/> <xs:element ref='error' minOccurs='0'/> </xs:sequence> <xs:attribute name='from' type='xs:string' use='required'/> <xs:attribute name='id' type='xs:NMTOKEN' use='optional'/> <xs:attribute name='to' type='xs:string' use='required'/> <xs:attribute name='type' use='optional' default='normal'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='chat'/> <xs:enumeration value='error'/> <xs:enumeration value='groupchat'/> <xs:enumeration value='headline'/> <xs:enumeration value='normal'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute ref='xml:lang' use='optional'/> </xs:complexType> </xs:element> <xs:element name='body'> <xs:complexType> <xs:simpleContent> <xs:extension base='xs:string'> <xs:attribute ref='xml:lang' use='optional'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name='subject'> <xs:complexType> <xs:simpleContent> <xs:extension base='xs:string'> <xs:attribute ref='xml:lang' use='optional'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name='thread' type='xs:NMTOKEN'/> <xs:element name='presence'> <xs:complexType> <xs:sequence> <xs:choice minOccurs='0' maxOccurs='unbounded'> <xs:element ref='show'/> <xs:element ref='status'/> <xs:element ref='priority'/> </xs:choice> <xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/> <xs:element ref='error' minOccurs='0'/> </xs:sequence> <xs:attribute name='from' type='xs:string' use='required'/> <xs:attribute name='id' type='xs:NMTOKEN' use='optional'/> <xs:attribute name='to' type='xs:string' use='required'/> <xs:attribute name='type' use='optional'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='subscribe'/> <xs:enumeration value='subscribed'/> <xs:enumeration value='unsubscribe'/> <xs:enumeration value='unsubscribed'/> <xs:enumeration value='unavailable'/> <xs:enumeration value='probe'/> <xs:enumeration value='error'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute ref='xml:lang' use='optional'/> </xs:complexType> </xs:element> <xs:element name='show'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='away'/> <xs:enumeration value='chat'/> <xs:enumeration value='dnd'/> <xs:enumeration value='xa'/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name='status'> <xs:complexType> <xs:simpleContent> <xs:extension base='xs:string'> <xs:attribute ref='xml:lang' use='optional'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name='priority' type='xs:byte'/> <xs:element name='iq'> <xs:complexType> <xs:sequence> <xs:any namespace='##other' minOccurs='0' maxOccurs='1'/> <xs:element ref='error' minOccurs='0' maxOccurs='1'/> </xs:sequence> <xs:attribute name='from' type='xs:string' use='required'/> <xs:attribute name='id' type='xs:NMTOKEN' use='required'/> <xs:attribute name='to' type='xs:string' use='required'/> <xs:attribute name='type' use='required'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='get'/> <xs:enumeration value='set'/> <xs:enumeration value='result'/> <xs:enumeration value='error'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute ref='xml:lang' use='optional'/> </xs:complexType> </xs:element> <xs:element name='error'> <xs:complexType> <xs:sequence xmlns:err='urn:ietf:params:xml:ns:xmpp-streams'> <xs:group ref='err:streamErrorGroup'/> <xs:element ref='err:text' minOccurs='0' maxOccurs='1'/> </xs:sequence> <xs:attribute name='code' type='xs:byte' use='optional'/> <xs:attribute name='type' use='required'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='cancel'/> <xs:enumeration value='continue'/> <xs:enumeration value='modify'/> <xs:enumeration value='auth'/> <xs:enumeration value='wait'/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> </xs:schema>