XMPP之流协商过程

版权所有,转载请注明出处:http://guangboo.org/2013/03/08/xmpp-stream-negotiate-precess

由于接收端是作为其所服务域的守护者,它会对连接来的客户端提出一些条件。至少,在接收端在接收请求端发送来的XML节点前,需要对请求方进行身份验证。然而,接收方也可能要考虑一些其他比身份验证更有强制协商性的条件,如采用TLS加密通讯。当然接收方会通知请求方,提出自己的条件,这个通知是采用“流特性”的方式进行的---这是请求方在接收方接收其发出的XML节点前,必须要完成的一组协议交互过程,当然有些协议交互过程是自愿的,但有些可能会优化XML流的处理过程(如在应用层建立压缩机制)。

有了这些连接条件,也就意味着协商的必要性。由于TCP, TLS和SASL等都有先后顺序,那也就表示协商也要分阶段处理。有两个因素决定了这个处理顺序:(1)是否提供一个流特性,要看实体是否需要,即可能只有某些实体才依赖这个特性;也可能依赖于某些其他特性的协商,就是说在某些其他特性协商后才能提供该流特性(如资源绑定只有在SASL验证之后才能提供);(2)流特性可以是强制协商的,也可以是自愿协商的;最后,出于安全原因,流的各部分需要在完成对某些特性的交互的定义后,丢弃一些在协商过程中得到的能力(如规范中定义的SASL验证机制,当通过SASL验证完毕后,TLS连接即被丢弃和而SASL在安全层建立时的SASL)。这一般要在当前TCP连接中,通过重新发送初始化流来完成。

流特性格式

如果请求方发生的初始化流中包含version属性,并且属性值只是是1.0,那么接收方在发送完反馈的初始化流之后,必须发送<features/>子节点,以通知请求方完成协商过程所需要的条件。条件是以<features/>的子节点的形式发送的,每个子节点表示一个条件。<features/>可以包含一个子节点,多个子节点,也可以不包含任何节点,子节点的顺序不做要求。

如果一个特定的流特性是可以强制协商的,那么它的定义就需要完成以下一种操作:

  1. 特性本身就是被要求为强制协商的(如XMPP客户端的资源绑定);或者
  2. 在一次交互过程中,为接收方指定一种方式来标记特性是强制协商的(如,STARTTLS,它是通过在该流特性中添加一个空的<required/>节点来实现的,但这不是所有特性都可以使用这样的方式);对于新的强制协商特性来说,还是推荐像STARTTLS这样,在特性节点中添加<required/>节点来实现。

由于没有通用的格式或方式来标记特性是否为强制性的,接收方也无法做出正确的判断,从而导致无法完成流协商。但是,尽管存在这样的问题,但是XMPP协议工作组认为这样的情况是很罕见的,因此没有必要寻找通用的解决方案。

出于安全原因,某些流特性在完成流协商后,有必要要求请求方重新发送初始化流(如TLS,及 在安全层建立时的SASL特性)。如果一个特性是这样的,那么它的定义就需要体现出“协商完后,需要重启”的特征。

如果<features/>节点中只是还包含一个强制协商的特性,那么就表示流协商并没有完成,就需要请求方必须进一步对特性进行协商。如:

R: <stream:features>
     <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
       <required/>
     </starttls>
   </stream:features>

<features/>节点可能包含多个强制协商的特性,就意味着请求方可以在一次协商阶段中,从这些特性中从中做出选择。例如,未来可能有一项技类似于TLS的技术,那么接收方就可能需要在同一协商阶段支持TLS和这项技术。但这只适用于给定的一个协商阶段,而不适用于强制协商的不同阶段(如,接收方不需要STARTTLS和SASL都是强制协商的,或SASL和资源绑定是强制协商的,因为TLS是在SASL之前就需要协商的,SASL在资源绑定之前就需要协商的)。

如一个<features/>节点既包含强制协商特性也包含自愿协商特性,可以判断协商没有完成,但是请求方可能需要先完成自愿协商的特性,然后在试着协商强制特性。如:

R: <stream:features>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
     <compression xmlns='http://jabber.org/features/compress'>
       <method>zlib</method>
       <method>lzw</method>
     </compression>
   </stream:features>

如一个<features/>节点只包含自愿协商的特性,那么就意味着协商已经完成,请求方就可以开始发生XML节(message, presence, iq等)了,但是如果请求反需要改特性的话,也可以进一步协商这些特性。如:

R: <stream:features>
     <compression xmlns='http://jabber.org/features/compress'>
       <method>zlib</method>
       <method>lzw</method>
     </compression>
   </stream:features>

如果<features/>节点时空的,那么就表示协商完成,请求方可以发生XML节(message, presence, iq等)了。如:

R: <stream:features/>

重启

特性协商成功后有必要重启流,双方都必须考虑替换之前的流,但一定不能发送关闭流</stream>,也一定不能终止当前TCP连接;相反的,双方一定要重用当前连接,当然连接可能出于新的状态下(如,由于TLS协商的缘故,连接已被加密)。请求方必须发送新的初始化流,接收方接到新的初始化流后,在发送反馈流之前,必须生成新的流ID(一定不能重用之前的老ID)。

重发特性

流重启之后,接收方必须发送一个更新后的流特性列表,如果没有特性需要进一步协商,或者可能只有特性的组合的话,更新后的特性列表可能就是空的。

协商完成

接收方通过给请求方发送空的<features/>节点,或只包含自愿协商的特性的<features/>节点的方式,来决定协商的完成。之后,请求方可能发送一个空的<features/>节点,但一定不能发送其他附加的特性(如果接收方有新的特性需要发送的话,最好限制在强制协商或紧急的安全特性上,那么可以通过发送关闭流,并带一个<reset/>的错误节点,然后在请求方重新连接时处理新特性。最好通过交叉的方式关闭现有的流,避免所有的初始实体都一起重连)。流协商完成后,请求方就可以发送XML节(message, presence, iq等)了。

需要注意的是,由于历史原因,资源绑定不适用于上述规则,因为它是客户端使用XML节来实现强制协商的。

请求方在协商完成之前,一定不能尝试向其他实体或连接的服务器发送XML节(message, presence, iq等)。即使请求方发送了,接收方也一定不能接收,而一定要关闭流,并带<not-authorized/>流错误。该规则只适用于XML节(即<message/>, <presence/>和<iq/>等内容命名空间限定的节点),而不适用于流协商时使用的XML节点(如,用于完成TLS和SASL协商的节点)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值