xmpp协议7
6.6. S/S 的例子
下面的例子展示了一个服务器与另一个服务器用SASL认证的数据流,通常在成功的TLS协商后(注意:下面交叉的步骤用于阐述失败情况下的协议;它们不是很详尽,且不是必需是例子中传送的数据引发的)。
Step 1: 服务器1向服务器2初始化流:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 2: 服务器2响应,通过发送一个流标识服务器1:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='s2s_234'
version='1.0'>
Step 3: 服务器2告知服务器1可用的认证机制:
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>KERBEROS_V4</mechanism>
</mechanisms>
</stream:features>
Step 4: 服务器1选择一个认证机制:
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='DIGEST-MD5'/>
Step 5: 服务器2发送一个以BASE64编码的召唤给服务器1:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9
ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz
</challenge>
解码后的召唤是:
realm="somerealm",nonce="OA6MG9tEQGm2hh",\
qop="auth",charset=utf-8,algorithm=md5-sess
Step 5 (alt): 服务器2返回错误到服务器1:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<incorrect-encoding/>
</failure>
</stream:stream>
Step 6: 服务器1发送以BASE64编码的响应给召唤:
<respon** *mlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9ImV4YW1wbGUub3JnIixyZWFsbT0ic29tZXJlYWxtIixub25j
ZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5j
PTAwMDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5v
cmciLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3
LGNoYXJzZXQ9dXRmLTgK
</response>
解码后的响应是:
username="example.org",realm="somerealm",\
nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
nc=00000001,qop=auth,digest-uri="xmpp/example.org",\
response=d388dad90d4bb*760*152321*2143*f7,charset=utf-8
Step 7: 服务器2发送又一个以BASE64编码的召唤给服务器1:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
</challenge>
解码后的召唤是:
rspauth=ea40f60335c427b5527b84dbabcdfffd
Step 7 (alt): 服务器2返回错误到服务器1:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<invalid-authzid/>
</failure>
</stream:stream>
Step 8: 服务器1发送响应给召唤:
<respon** *mlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 8 (alt): 服务器1 中断协商:
<abort xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9: 服务器2告知服务器1认证成功:
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9 (alt): 服务器2告知服务器1认证失败:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<aborted/>
</failure>
</stream:stream>
Step 10: 服务器1初始化一个新的流到服务器2:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 11: 服务器2通过发送一个流header,连同任何附加特性(或者一个空的特性元素)到服务器1来响应:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='s2s_345'
version='1.0'>
<stream:features/>
7. 资源绑定
在与接收实体SASL协商后,初始实体可能(MAY)想或需要绑定一个特定的资源到流。通常这只应用于客户端:为了与编址格式及这里指定的节传输规则相一致,这儿必须(MUST)有一个与客户端的<node@domain>相关的资源标识符(由服务器产生或由客户端应用程序提供);这确保了流中使用的地址是一个<node@domain/resource>形式的“完全的JID”。
在接收到SASL协商中的成功指示后,客户端必须(MUST)发送一个新的流header到服务器,服务器则必须(MUST)响应一个流 header及一个可用的流特性列表到客户端。特别是,如果服务器需要客户端在成功的SASL协商后绑定一个资源到流,该服务器必须(MUST)包含一个空的在‘urn:ietf:params:xml:ns:xmpp-bind’命名空间下的<bind/>元素于它呈现给可户端的流特性列表中,此列表是在SASL协商成功后在发送了响应流中的流header后(不是之前)呈现的:
服务器注册资源绑定特性到客户端:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_345'
from='example.com'
version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
在这样被告知需要绑定资源后,客户端必须(MUST)绑定一个资源到流,通过发送给服务器一个type为“set”的IQ节,它包含在‘urn:ietf:params:xml:ns:xmpp-bind'’命名空间下的数据。
如果客户端希望让服务器为它生成资源标识符,它发送一个type为“set”的IQ节,包含一个空的<bind/>元素:
客户端请求服务器绑定资源:
<iq type='set' id='bind_1'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</iq>
一个支持资源绑定的服务器必须(MUST)能够为客户端生成一个资源标识符。一个由服务器生成的资源标识符必须(MUST)唯一,以<node@domain>这样的形式 。
如果客户端希望指定资源标识符,它发送一个type为“set”的IQ节,包含期望的资源标识符作为一个<resource/>元素的XML字符数据,该<resource/>元素是<bind/>元素的子元素:
客户端绑定一个资源:
<iq type='set' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
</iq>
一旦服务器为客户端生成一个资源标识符,或是接受了客户端提供的资源标识符,它必须(MUST)返回一个type为“result”的IQ节到客户端,此IQ节必须(MUST)包含一个<jid/>子元素,用于为服务器决定的已连接资源指定完全的JID:
服务器告知客户端成功绑定资源:
<iq type='result' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<jid>somenode@example.com/someresource</jid>
</bind>
</iq>
一个服务器应该(SHOULD)接受客户端提供的资源标识符,但是可以(MAY)用一个服务器生成的资源标识符重写它;在这种情况下,服务器不应该(SHOULD NOT)返回一个节错误(例如,<forbidden/>)到客户端,但是却应该(SHOULD)在上面展示的IQ结果中传达生成的资源标识符给客户端。
当一个客户端提供一个资源标识符,以下的节错误可能存在(参见节错误):
* 服务器依照Resourceprep处理不了所提供的资源标识符。
* 客户端不允许绑定资源到流(例如,节点或用户达到了允许连接的资源数量的限度)。
* 所提供的资源标识符已经在使用,但是服务器不允许用相同的标识符绑定多个连接的资源。
这些错误因素的协议展示如下:
处理不了资源标识符:
<iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
不允许客户端绑定资源:
<iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
使用到了资源标识符:
<iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
如果,在完成资源绑定步骤之前,可户端尝试发送一个不同于IQ节的,带有在‘urn:ietf:params:xml:ns:xmpp-bind’ 命名空间下的<bind/>子节点的XML节,服务器禁止(MUST NOT)处理这个节且应该(SHOULD)返回一个<not-authorized/>节错误到客户端。
下面的例子展示了一个服务器与另一个服务器用SASL认证的数据流,通常在成功的TLS协商后(注意:下面交叉的步骤用于阐述失败情况下的协议;它们不是很详尽,且不是必需是例子中传送的数据引发的)。
Step 1: 服务器1向服务器2初始化流:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 2: 服务器2响应,通过发送一个流标识服务器1:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='s2s_234'
version='1.0'>
Step 3: 服务器2告知服务器1可用的认证机制:
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>KERBEROS_V4</mechanism>
</mechanisms>
</stream:features>
Step 4: 服务器1选择一个认证机制:
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='DIGEST-MD5'/>
Step 5: 服务器2发送一个以BASE64编码的召唤给服务器1:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9
ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz
</challenge>
解码后的召唤是:
realm="somerealm",nonce="OA6MG9tEQGm2hh",\
qop="auth",charset=utf-8,algorithm=md5-sess
Step 5 (alt): 服务器2返回错误到服务器1:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<incorrect-encoding/>
</failure>
</stream:stream>
Step 6: 服务器1发送以BASE64编码的响应给召唤:
<respon** *mlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9ImV4YW1wbGUub3JnIixyZWFsbT0ic29tZXJlYWxtIixub25j
ZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5j
PTAwMDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5v
cmciLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3
LGNoYXJzZXQ9dXRmLTgK
</response>
解码后的响应是:
username="example.org",realm="somerealm",\
nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
nc=00000001,qop=auth,digest-uri="xmpp/example.org",\
response=d388dad90d4bb*760*152321*2143*f7,charset=utf-8
Step 7: 服务器2发送又一个以BASE64编码的召唤给服务器1:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
</challenge>
解码后的召唤是:
rspauth=ea40f60335c427b5527b84dbabcdfffd
Step 7 (alt): 服务器2返回错误到服务器1:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<invalid-authzid/>
</failure>
</stream:stream>
Step 8: 服务器1发送响应给召唤:
<respon** *mlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 8 (alt): 服务器1 中断协商:
<abort xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9: 服务器2告知服务器1认证成功:
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9 (alt): 服务器2告知服务器1认证失败:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<aborted/>
</failure>
</stream:stream>
Step 10: 服务器1初始化一个新的流到服务器2:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 11: 服务器2通过发送一个流header,连同任何附加特性(或者一个空的特性元素)到服务器1来响应:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='s2s_345'
version='1.0'>
<stream:features/>
7. 资源绑定
在与接收实体SASL协商后,初始实体可能(MAY)想或需要绑定一个特定的资源到流。通常这只应用于客户端:为了与编址格式及这里指定的节传输规则相一致,这儿必须(MUST)有一个与客户端的<node@domain>相关的资源标识符(由服务器产生或由客户端应用程序提供);这确保了流中使用的地址是一个<node@domain/resource>形式的“完全的JID”。
在接收到SASL协商中的成功指示后,客户端必须(MUST)发送一个新的流header到服务器,服务器则必须(MUST)响应一个流 header及一个可用的流特性列表到客户端。特别是,如果服务器需要客户端在成功的SASL协商后绑定一个资源到流,该服务器必须(MUST)包含一个空的在‘urn:ietf:params:xml:ns:xmpp-bind’命名空间下的<bind/>元素于它呈现给可户端的流特性列表中,此列表是在SASL协商成功后在发送了响应流中的流header后(不是之前)呈现的:
服务器注册资源绑定特性到客户端:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_345'
from='example.com'
version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
在这样被告知需要绑定资源后,客户端必须(MUST)绑定一个资源到流,通过发送给服务器一个type为“set”的IQ节,它包含在‘urn:ietf:params:xml:ns:xmpp-bind'’命名空间下的数据。
如果客户端希望让服务器为它生成资源标识符,它发送一个type为“set”的IQ节,包含一个空的<bind/>元素:
客户端请求服务器绑定资源:
<iq type='set' id='bind_1'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</iq>
一个支持资源绑定的服务器必须(MUST)能够为客户端生成一个资源标识符。一个由服务器生成的资源标识符必须(MUST)唯一,以<node@domain>这样的形式 。
如果客户端希望指定资源标识符,它发送一个type为“set”的IQ节,包含期望的资源标识符作为一个<resource/>元素的XML字符数据,该<resource/>元素是<bind/>元素的子元素:
客户端绑定一个资源:
<iq type='set' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
</iq>
一旦服务器为客户端生成一个资源标识符,或是接受了客户端提供的资源标识符,它必须(MUST)返回一个type为“result”的IQ节到客户端,此IQ节必须(MUST)包含一个<jid/>子元素,用于为服务器决定的已连接资源指定完全的JID:
服务器告知客户端成功绑定资源:
<iq type='result' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<jid>somenode@example.com/someresource</jid>
</bind>
</iq>
一个服务器应该(SHOULD)接受客户端提供的资源标识符,但是可以(MAY)用一个服务器生成的资源标识符重写它;在这种情况下,服务器不应该(SHOULD NOT)返回一个节错误(例如,<forbidden/>)到客户端,但是却应该(SHOULD)在上面展示的IQ结果中传达生成的资源标识符给客户端。
当一个客户端提供一个资源标识符,以下的节错误可能存在(参见节错误):
* 服务器依照Resourceprep处理不了所提供的资源标识符。
* 客户端不允许绑定资源到流(例如,节点或用户达到了允许连接的资源数量的限度)。
* 所提供的资源标识符已经在使用,但是服务器不允许用相同的标识符绑定多个连接的资源。
这些错误因素的协议展示如下:
处理不了资源标识符:
<iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
不允许客户端绑定资源:
<iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
使用到了资源标识符:
<iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
如果,在完成资源绑定步骤之前,可户端尝试发送一个不同于IQ节的,带有在‘urn:ietf:params:xml:ns:xmpp-bind’ 命名空间下的<bind/>子节点的XML节,服务器禁止(MUST NOT)处理这个节且应该(SHOULD)返回一个<not-authorized/>节错误到客户端。