XEP-0077

来自Jabber/XMPP中文翻译计划
2011年11月30日 (三) 13:34Wangjxxxhi (讨论 | 贡献)的版本
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳转到: 导航, 搜索


本文的英文原文来自XEP-0077

XEP-0077:带内注册

摘要: 本文定义了一个XMPP协议扩展用于基于XMPP的即时消息服务器和其他XMPP网络上的服务(例如群聊房间以及和非XMPP的IM服务之间的网关)的带内注册. 本协议可以通过使用数据表单来扩展, 这可以使得服务在注册过程中能够收集广泛的信息. 本协议也支持带内变更密码和取消现有的注册.

作者: Peter Saint-Andre

版权: © 1999 - 2010 XMPP标准化基金会(XSF). 参见法律通告.

状态: 最终

类型: 标准跟踪

版本: 2.3

最后更新日期: 2009-09-15

注意: 这里定义的协议是XMPP标准化基金会的一个最终标准,对于实现和布署来说可以被认为是一个稳定技术.

目录

绪论

Jabber协议很早就包含了一个从即时消息服务器和相关服务进行带内注册的方法. 这个方法使用 'jabber:iq:register' 名字空间并且被广泛记载于Internet-Drafts和其他地方. 因为带内注册不是 RFC 2779 1必需的, 'jabber:iq:register' 名字空间的文档从 XMPP IM 2移除了. 本协议填补了这部分文件的空白.

要求

带内注册必须使一个实体能够向一个主机注册, 从一个主机取消现有的注册, 或从一个主机变更密码. 这里"host"的含义如下:

  1. 一个即时消息服务器, 如 XMPP IM 中所描述并且在 服务发现 [[XEP-0077#附录G:备注|3] 中的 category+type 标识为 "server/im"
  2. 一个附加的服务, 例如一个网关(见 网关互动 4) 或一个多用户聊天 5服务

如果必要, 关于信息收集的扩展性应该使用 数据表单 6.

用例

实体注册到一个主机

为了确定向一个主机注册需要哪些字段, 一个实体应该(SHOULD)首先发送一个 IQ get 给主机. 这个实体不应该(SHOULD NOT)通过先发送一个IQ set来尝试猜测需要的字段 , 因为需要的数据的性质是由服务决定的.

例子 1. 实体向主机请求注册字段

<iq type='get' id='reg1'>
  <query xmlns='jabber:iq:register'/>
</iq>

如果实体未曾注册并且主机支持带内注册, 主机必须(MUST)通知实体需要的注册字段. 如果主机不支持带内注册, 它必须(MUST)返回一个 <service-unavailable/> 错误. 如果一个主机重定向注册请求到一些其他的媒介(例如web网站), 它只可以(MAY)返回一个 <instructions/> 元素, 详见本文的 重定向 章节.

例子 2. 主机返回注册字段给实体

<iq type='result' id='reg1'>
  <query xmlns='jabber:iq:register'>
    <instructions>
      Choose a username and password for use with this service.
      Please also provide your email address.
    </instructions>
    <username/>
    <password/>
    <email/>
  </query>
</iq>

如果主机确定(基于'from'地址) 该实体已经注册, 它给该IQ get返回的应答IQ result中必须(MUST)包含一个空的<registered/>元素(表示该实体已注册), 应该(SHOULD)包含该实体当前已有的注册信息(尽管<password/>元素可以(MAY)是空的), 并且应该(SHOULD)包含一个<instructions/>元素(其XML字符数据可以(MAY)被修改以反映该实体已被注册的事实).

如果该主机是一个即时消息服务器, 在这个阶段它应该(SHOULD)假设请求的实体是未注册的,除非实体已经被验证(详见下文中的 注册到一个服务器 章节).

例子 3. 主机通知实体当前的注册

<iq type='result' id='reg1'>
  <query xmlns='jabber:iq:register'>
    <registered/>
    <username>juliet</username>
    <password>R0m30</password>
    <email>juliet@capulet.com</email>
  </query>
</iq>

如果实体还未注册, 该实体应该(SHOULD)提供必需的信息.

例子 4. 实体提供必需信息

<iq type='set' id='reg2'>
  <query xmlns='jabber:iq:register'>
    <username>bill</username>
    <password>Calliope</password>
    <email>bard@shakespeare.lit</email>
  </query>
</iq>

注意: 请求的实体必须(MUST)在IQ result中包含提供的所有元素信息(除了<instructions/>元素).

例子 5. 主机通知实体注册成功

<iq type='result' id='reg2'/>

反之, 注册可能失败. 可能的失败包括用户名冲突(期待的用户名已经被另一个实体使用)以及请求的实体未能提供完全的必需信息.

例子 6. 主机通知实体注册失败(用户名冲突)

<iq type='error' id='reg2'>
  <query xmlns='jabber:iq:register'>
    <username>bill</username>
    <password>m1cro$oft</password>
    <email>billg@bigcompany.com</email>
  </query>
  <error code='409' type='cancel'>
    <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>

如果请求的实体在注册时未提供所有的请求信息 7, 那么服务器或者服务必须(MUST)返回一个<not-acceptable/>错误给请求实体.

例子 7. 主机通知实体注册失败(一些必需的信息未提供)

<iq type='error' id='reg2'>
  <query xmlns='jabber:iq:register'>
    <username>bill</username>
    <password>Calliope</password>
  </query>
  <error code='406' type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>

如果主机需要超出以上的以及超过schema定义的数据元素的额外信息, 它应该(SHOULD)使用本文的 可扩展性 章节里描述的数据表单. (下面三个例子展示一个现有的账号注册到一个第三方服务, 而不是一个实体向一个服务器注册账号)


例子 8. 实体向主机请求注册字段

<iq type='get'
    from='juliet@capulet.com/balcony'
    to='contests.shakespeare.lit'
    id='reg3'>
  <query xmlns='jabber:iq:register'/>
</iq>

例子 9. 主机返回注册表单给实体

<iq type='result'
    from='contests.shakespeare.lit'
    to='juliet@capulet.com/balcony'
    id='reg3'>
  <query xmlns='jabber:iq:register'>
    <instructions>
      Use the enclosed form to register. If your Jabber client does not
      support Data Forms, visit http://www.shakespeare.lit/contests.php
    </instructions>
    <x xmlns='jabber:x:data' type='form'>
      <title>Contest Registration</title>
      <instructions>
        Please provide the following information
        to sign up for our special contests!
      </instructions>
      <field type='hidden' var='FORM_TYPE'>
        <value>jabber:iq:register</value>
      </field>
      <field type='text-single' label='Given Name' var='first'>
        <required/>
      </field>
      <field type='text-single' label='Family Name' var='last'>
        <required/>
      </field>
      <field type='text-single' label='Email Address' var='email'>
        <required/>
      </field>
      <field type='list-single' label='Gender' var='x-gender'>
        <option label='Male'><value>M</value></option>
        <option label='Female'><value>F</value></option>
      </field>
    </x>
  </query>
</iq>

然后用户应该(SHOULD)返回表单:

例子 10. 用户提交注册表单

<iq type='set'
    from='juliet@capulet.com/balcony'
    to='contests.shakespeare.lit'
    id='reg4'>
  <query xmlns='jabber:iq:register'>
    <x xmlns='jabber:x:data' type='submit'>
      <field type='hidden' var='FORM_TYPE'>
        <value>jabber:iq:register</value>
      </field>
      <field type='text-single' label='Given Name' var='first'>
        <value>Juliet</value>
      </field>
      <field type='text-single' label='Family Name' var='last'>
        <value>Capulet</value>
      </field>
      <field type='text-single' label='Email Address' var='email'>
        <value>juliet@capulet.com</value>
      </field>
      <field type='list-single' label='Gender' var='x-gender'>
        <value>F</value>
      </field>
    </x>
  </query>
</iq>

注册到一个服务器

当一个未注册的实体和一个服务器而不是一个服务交互时必须特别注意. 通常, 一个服务器允许带内注册以使实体能够在Jabber网络里面自举"bootstrap"参与; 这个 bootstrapping 发生了一个未注册以及未验证的实体向一个服务器打开一个TCP连接并立刻完成该服务器的注册用例的时候, 然后使用这个全新注册的标识进行验证. 如上所述, 当一个服务器收到一个 IQ-get 用于注册信息, 它应该(SHOULD)假设请求实体是未注册的除非该实体已经验证.

取决于本地服务的供应, 如果一个未注册的实体在验证之前尝试太多次数的注册,或者一个实体成功完成注册用例之后尝试注册第二个身份,那么一个服务器可以(MAY)返回一个<not-acceptable/>节错误; 如果未注册的实体在验证之前等待太久或者在成功完成注册用例之后尝试完成一个动作而这个动作不是在做验证, 一个服务器也可以(MAY)返回一个<not-authorized/>流错误.

实体取消现存注册

'jabber:iq:register'名字空间允许一个实体也能够从一个主机取消一个注册, 通过发送一个包含<remove/>元素的 IQ set. 该主机必须(MUST)根据 IQ get 的 'from' 地址来确定请求实体的身份.

例子 11. 实体请求注销现存注册

<iq type='set' from='bill@shakespeare.lit/globe' id='unreg1'>
  <query xmlns='jabber:iq:register'>
    <remove/>
  </query>
</iq>

例子 12. 主机通知实体成功注销

<iq type='result' to='bill@shakespeare.lit/globe' id='unreg1'/>

有两种情形:

  1. 如果实体从他的"home"服务器取消注册(也就是说,维护它的XMPP帐号的服务器), 那么该实体不应该(SHOULD NOT)包含一个 'from' 或 'to' 地址在移除请求中, 该服务器应该(SHOULD)返回一个<not-authorized/>流错误并且终止该实体所有激活的会话. 该服务器应该(SHOULD)执行的移除操作以其收到移除请求的当前会话或连接的相关的纯JID (<node@domain.tld>)为准. 如果服务器是一个即时消息和出席信息服务期并遵循 RFC 3921 8, 该服务器也应该(SHOULD)取消所有和该实体相关的现存的出席信息订阅(储存在实体的花名册中).
  2. 如果实体从一个服务而不是它的宿主服务器取消注册, 它的宿主服务器必须(MUST)贴一个'from'地址到移除请求中, 这个遵循 XMPP Core 的地址应为该实体的全 JID (<node@domain.tld/resource>). 该服务必须(MUST)基于'from'地址的纯JID (<node@domain.tld>)部分来执行移除操作.

如下所述, 各种错误可能发生.

表 1: 注销出错例子

条件 描述
<bad-request/> <remove/> 元素不只是<query/> 元素的唯一子元素.
<forbidden/> 发送者没有足够的权限取消注册.
<not-allowed/> 没有发送者被允许在带内取消注册.
<registration-required/> 发送移除请求的实体未曾注册.
<unexpected-request/> 主机是一个即时消息服务器而 IQ get 不包含一个 'from' 地址, 因为该实体不是注册到该服务器.

例子 13. 主机通知客户端注销失败(错误的请求)

<iq type='error' from='shakespeare.lit' to='bill@shakespeare.lit/globe' id='unreg1'>
  <error code='400' type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>

例子 14. 主机通知客户端注销失败(禁止)

<iq type='error' from='shakespeare.lit' to='bill@shakespeare.lit/globe' id='unreg1'>
  <error code='401' type='cancel'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>

例子 15. 主机通知客户端注销失败(不允许)

<iq type='error' from='shakespeare.lit' to='bill@shakespeare.lit/globe' id='unreg1'>
  <error code='405' type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>

一个给定的布署可以(MAY)选择在取消注册之前要求额外的信息(例如旧密码或以前收集的个人信息). 为了做到这一点, 服务器或服务应该(SHOULD)在错误节里面返回一个数据表单:

例子16. 服务器在错误信息中返回注销表单

<iq type='error' from='shakespeare.lit' to='bill@shakespeare.lit/globe' id='unreg1'>
  <query xmlns='jabber:iq:register'>
    <x xmlns='jabber:x:data' type='form'>
      <title>Password Change</title>
      <instructions>Use this form to cancel your registration.</instructions>
      <field type='hidden' var='FORM_TYPE'>
        <value>jabber:iq:register:cancel</value>
      </field>
      <field type='text-single' label='Username' var='username'>
        <required/>
      </field>
      <field type='text-private' label='Password' var='password'>
        <required/>
      </field>
      <field type='text-single' label='Mother&apos;s Maiden Name' var='x-mmn'>
        <required/>
      </field>
    </x>
  </query>
  <error code='405' type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>

然后用户应该(SHOULD)返回表单:

例子 17. 用户返回注销表单

<iq type='set' from='bill@shakespeare.lit/globe' to='shakespeare.lit' id='unreg2'>
  <query xmlns='jabber:iq:register'>
    <x xmlns='jabber:x:data' type='submit'>
      <field type='hidden' var='FORM_TYPE'>
        <value>jabber:iq:register:cancel</value>
      </field>
      <field type='text-single' var='username'>
        <value>bill@shakespeare.lit</value>
      </field>
      <field type='text-private' var='password'>
        <value>theglobe</value>
      </field>
      <field type='text-single' var='x-mmn'>
        <value>Throckmorton</value>
      </field>
    </x>
  </query>
</iq>

用户