《Extensible Messaging and Presence Protocol (XMPP): Core》阅读笔记(一)

简介:
文档链接:《Extensible Messaging and Presence Protocol (XMPP): Core》

客户和服务器之间端口为5222,服务器之间的端口为5269.

通信协议格式:

复制代码
|--------------------|
| <stream>           |
|--------------------|
| <presence>         |
|   <show/>          |
| </presence>        |
|--------------------|
| <message to='foo'> |
|   <body/>          |
| </message>         |
|--------------------|
| <iq to='bar'>      |
|   <query/>         |
| </iq>              |
|--------------------|
|                 |
|--------------------|
| </stream>          |

复制代码

客户端和服务器之间维持一个TCP连接,服务器之间维持两个TCP连接。
想传输数据之间必须得通过验证,否则不予处理
To:用于客户端到服务器端,
From:用于服务器到客户端
Id:用于服务器到客户端,是服务器端生成的会话id号
Xml:lang:包括在客户端的初始流种,指定XML数据的字体,服务器端应该记住此设置,若客户端没有设置,则服务器使用其默认配置,并在应答流中通知给客户端。


复制代码
         |  initiating to receiving  |  receiving to initiating

---------+---------------------------+-----------------------

to       |  hostname of receiver     |  silently ignored

from     |  silently ignored         |  hostname of receiver

id       |  silently ignored         |  session key

xml:lang |  default language         |  default language

version  |  signals XMPP 1.0 support |  signals XMPP 1.0 support


复制代码



若客户端在初始化流包中包含了版本字段,则服务器在应答中必须包含一个<features/>元素,从而让客户端知道服务器支持的特性是哪些,以便客户端和服务器就某些特性进行协商。

流级别的错误是不可恢复的,因此一旦出现,则探测到错误的实体必须发送一个流错误信息给对方,并且发送</stream>结束符,关闭底层TCP连接。

一次简单的会话示例:



复制代码
C: <?xml version='1.0'?>

   <stream:stream

       to='example.com'

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       version='1.0'>

S: <?xml version='1.0'?>

   <stream:stream

       from='example.com'

       id='someid'

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       version='1.0'>

  encryption, authentication, and resource binding 

C:   <message from='juliet@example.com'

              to='romeo@example.net'

              xml:lang='en'>

C:     <body>Art thou not Romeo, and a Montague?</body>

C:   </message>

S:   <message from='romeo@example.net'

              to='juliet@example.com'

              xml:lang='en'>

S:     <body>Neither, fair saint, if either thee dislike.</body>

S:   </message>

C: </stream:stream>

S: </stream:stream>


复制代码



 
一次发生错误的会话:




复制代码
C: <?xml version='1.0'?>

   <stream:stream

       to='example.com'

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       version='1.0'>

S: <?xml version='1.0'?>

   <stream:stream

       from='example.com'

       id='someid'

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       version='1.0'>

  encryption, authentication, and resource binding 

C: <message xml:lang='en'>

     <body>Bad XML, no closing body tag!

   </message>

S: <stream:error>

    <xml-not-well-formed

        xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>

   </stream:error>

S: </stream:stream>


复制代码



 
出于安全性的考虑,在客户和服务器之间,服务器之间可能会要求先进行TLS 安全性的验证,而且必须在SASL协商之前完成。


客户到服务器示例:


复制代码
Step 1: 客户端初始化到服务器端的流: 

<stream:stream

    xmlns='jabber:client'

    xmlns:stream='http://etherx.jabber.org/streams'

    to='example.com'

    version='1.0'>

Step 2: 服务器的应答,回送一个<stream>标签,并指明会话id: 

<stream:stream

    xmlns='jabber:client'

    xmlns:stream='http://etherx.jabber.org/streams'

    id='c2s_123'

    from='example.com'

    version='1.0'>

Step 3: 服务器发送STARTTLS extension 给客户端,并且指明验证机制和其他支持的流特性: 

<stream:features>

  <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>

    <required/>

  </starttls>

  <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

    <mechanism>DIGEST-MD5</mechanism>

    <mechanism>PLAIN</mechanism>

  </mechanisms>

</stream:features>

Step 4:客户端发送STARTTLS命令给服务器: 

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

Step 5: 服务器通知客户端,它被允许继续处理: 

<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

Step 5 (alt): 服务器通知客户,TLS协商失败,关闭流和TCP连接: 

<failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

</stream:stream>

Step 6:客户端和服务器端准备在现有的TCP连接上完成TLS验证。

Step 7: 若TLS验证成功,客户端初始化一个到服务器的新流: 

<stream:stream

    xmlns='jabber:client'

    xmlns:stream='http://etherx.jabber.org/streams'

    to='example.com'

    version='1.0'>

Step 7 (alt): 若TLS验证失败,服务器关闭TCP连接

Step 8:服务器回送应答信息,包含了一个流头部和其他可用的流特性: 

<stream:stream

    xmlns='jabber:client'

    xmlns:stream='http://etherx.jabber.org/streams'

    from='example.com'

    id='c2s_234'

    version='1.0'>

<stream:features>

  <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

    <mechanism>DIGEST-MD5</mechanism>

    <mechanism>PLAIN</mechanism>

    <mechanism>EXTERNAL</mechanism>

  </mechanisms>

</stream:features>

Step 9: 客户端继续进行SASL验证。  


复制代码



服务器到服务器示例:

复制代码
Step 1: Server1 initiates stream to Server2: 
<stream:stream
    xmlns='jabber:server'
    xmlns:stream='http://etherx.jabber.org/streams'
    to='example.com'
    version='1.0'>
Step 2: Server2 responds by sending a stream tag to Server1: 
<stream:stream
    xmlns='jabber:server'
    xmlns:stream='http://etherx.jabber.org/streams'
    from='example.com'
    id='s2s_123'
    version='1.0'>
Step 3: Server2 sends the STARTTLS extension to Server1 along with authentication mechanisms and any other stream features: 
<stream:features>
  <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
    <required/>
  </starttls>
  <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
    <mechanism>DIGEST-MD5</mechanism>
    <mechanism>KERBEROS_V4</mechanism>
  </mechanisms>
</stream:features>
Step 4: Server1 sends the STARTTLS command to Server2: 
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
Step 5: Server2 informs Server1 that it is allowed to proceed: 
<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
Step 5 (alt): Server2 informs Server1 that TLS negotiation has failed and closes stream: 
<failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
</stream:stream>
Step 6: Server1 and Server2 attempt to complete TLS negotiation via TCP. 
Step 7: If TLS negotiation is successful, Server1 initiates a new stream to Server2: 
<stream:stream
    xmlns='jabber:server'
    xmlns:stream='http://etherx.jabber.org/streams'
    to='example.com'
    version='1.0'>
Step 7 (alt): If TLS negotiation is unsuccessful, Server2 closes TCP connection. 
Step 8: Server2 responds by sending a stream header to Server1 along with any available stream features: 
<stream:stream
    xmlns='jabber:server'
    xmlns:stream='http://etherx.jabber.org/streams'
    from='example.com'
    id='s2s_234'
    version='1.0'>
<stream:features>
  <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
    <mechanism>DIGEST-MD5</mechanism>
    <mechanism>KERBEROS_V4</mechanism>
    <mechanism>EXTERNAL</mechanism>
  </mechanisms>
</stream:features>
Step 9: server1继续进行SASL验证 

复制代码

在TLS验证后,进行SASL验证

客户到服务器示例:

Step 1: 客户端初始到服务器的流:

 

<stream:stream
    xmlns='jabber:client'
    xmlns:stream='http://etherx.jabber.org/streams'
    to='example.com'
    version='1.0'>

Step 2:服务器发送应答:

复制代码
<stream:stream
    xmlns='jabber:client'
    xmlns:stream='http://etherx.jabber.org/streams'
    id='c2s_234'
    from='example.com'
    version='1.0'>

复制代码
  Step 3:服务器通知客户可选的验证机制:

复制代码
<stream:features>
  <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
    <mechanism>DIGEST-MD5</mechanism>
    <mechanism>PLAIN</mechanism>
  </mechanisms>
</stream:features>

复制代码
Step 4: 客户端选择一种验证机制:

<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
      mechanism='DIGEST-MD5'/>

Step 5: 服务器发送BASE64编码过的应答数据给客户端: 

 

<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgi
LGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==
</challenge>

 解码后的数据为:

realm="somerealm",nonce="OA6MG9tEQGm2hh",\
qop="auth",charset=utf-8,algorithm=md5-sess

Step 5 (alt):服务器返回错误给客户端:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
  <incorrect-encoding/>
</failure>
</stream:stream>


 Step 6: 客户端发送一个BASE64编码的应答数据给服务器:

复制代码
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i
T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw
MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i
LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo
YXJzZXQ9dXRmLTgK
</response>

复制代码
解码后的应答消息是:

username="somenode",realm="somerealm",\
nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
nc=00000001,qop=auth,digest-uri="xmpp/example.com",\
response=d388dad90d4bbd760a152321f2143af7,charset=utf-8

Step 7: 服务器发送第二个BASE64编码的challenge数据给客户:

<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
</challenge>


解码后的challenge是:

rspauth=ea40f60335c427b5527b84dbabcdfffd

Step 7 (alt): 服务器返回错误给客户:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
  <temporary-auth-failure/>
</failure>
</stream:stream>

Step 8: 客户返回应答消息给服务器:

<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

Step 9: 服务器通知客户成功通过验证:

<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

 Step 9 (alt):服务器通知客户验证失败:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
  <temporary-auth-failure/>
</failure>
</stream:stream>


Step 10:客户端初始化一个到服务器的新流:

 

<stream:stream
    xmlns='jabber:client'
    xmlns:stream='http://etherx.jabber.org/streams'
    to='example.com'
    version='1.0'>

Step 11: 服务器返回一个流头部,包含了服务器支持的流特性:

复制代码
<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'/>
  <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
</stream:features>

复制代码



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/07/15/1243402.html,如需转载请自行联系原作者
目录
相关文章
|
6月前
|
人工智能 JavaScript API
【HarmonyOS NEXT+AI】问答03:找不到DevEco Studio Cangjie Plugin下载链接?
本文针对学员在“HarmonyOS NEXT+AI大模型打造智能助手APP(仓颉版)”课程中提出的问题进行解答:为何无法在华为开发者社区官网找到DevEco Studio Cangjie Plugin下载链接。文中详细介绍了Cangjie Plugin的功能及获取方式,包括STS和Canary版本的申请流程,并提供了学习仓颉编程语言的资源与建议。对于普通开发者,STS版本是当前首选;同时,通过课程与官方教程,可快速掌握仓颉语言核心语法及API,助力开发HarmonyOS NEXT AI智能助手应用。
326 3
【HarmonyOS NEXT+AI】问答03:找不到DevEco Studio Cangjie Plugin下载链接?
|
编译器 Linux Shell
外部函数(External Functions)在C语言中的应用
外部函数(External Functions)在C语言中的应用
411 0
|
存储 NoSQL 数据处理
Redis Lua脚本:赋予Redis更强大的逻辑与功能
Redis Lua脚本:赋予Redis更强大的逻辑与功能
271 0
|
监控 Linux 网络安全
Domain Admin域名和SSL证书过期监控到期提醒
用于解决,不同业务域名SSL证书,申请自不同的平台,到期后不能及时收到通知,导致线上访问异常,被老板责骂的问题。同时,Domain Admin也是一个轻量级监控方案,占用系统资源较少,安装包仅1.5 MB。基于Python3 + Vue3.js 技术栈实现的域名和SSL证书监测平台。支持证书:单域名证书、多域名证书、通配符证书、IP证书、自签名证书。通知渠道:支持邮件、Webhook、企业微信、钉钉、飞书等通知方式。证书部署: 单一主机部署、多主机部署、动态主机部署。的过期监控,到期提醒。
949 3
Domain Admin域名和SSL证书过期监控到期提醒
|
存储 测试技术 索引
【题解】—— LeetCode一周小结21
LeetCode每日一道一周小结21
163 8
|
机器学习/深度学习 算法 数据挖掘
每个程序员都应该知道的 40 个算法(二)(2)
每个程序员都应该知道的 40 个算法(二)
132 2
|
JavaScript 前端开发 Python
javascript中的强制类型转换和自动类型转换
javascript中的强制类型转换和自动类型转换
142 1
|
机器学习/深度学习 人工智能 算法
卷积神经网络CNN实现mnist手写数字识别
卷积神经网络CNN实现mnist手写数字识别
卷积神经网络CNN实现mnist手写数字识别
|
数据采集 机器学习/深度学习 编解码
数字孪生核心技术揭秘(三):倾斜摄影
对真实世界的自动化三维重建一直是CG/CV行业前赴后继不断尝试解决的难题;目前业内的进展,对于微型场景如单个饮料瓶等物体,结合AI已经可以实现语义化切割的自动三维重建,媲美人工建模。但是对于室外大场景的自动三维重建,从算法到采集硬件等等,都还未能做到类似微型场景的理想水平。 目前,倾斜摄影虽然在模型语义化分割、模型精度等方面不太完美,但是在贴近真实世界、过程自动化、实施成本、整体技术链成熟度等方面,已经是市面上最理想的低成本大规模三维重建技术方案。 随着国家政策的鼓励和“全景中国”的推进,预计倾斜摄影将会成为数字孪生项目的主流三维模型来源之一。
9908 2
java202304java学习笔记第六十天-ssm-spring配置文件-依赖注入5
java202304java学习笔记第六十天-ssm-spring配置文件-依赖注入5
94 0