转:http://blog.csdn.net/huwenfeng_2011/article/details/43413509

用户注册

注册流程:

1、客户端进行握手给服务端发送连接消息:

  1. <stream:stream to="192.168.2.104" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0"></stream:stream>

2、服务端回执:

  1. <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="hytest240" id="9fd61155" xml:lang="en" version="1.0">
  2. <stream:features>
  3. <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
  4. <mechanism>DIGEST-MD5</mechanism>
  5. <mechanism>JIVE-SHAREDSECRET</mechanism>
  6. <mechanism>PLAIN</mechanism>
  7. <mechanism>ANONYMOUS</mechanism>
  8. <mechanism>CRAM-MD5</mechanism>
  9. </mechanisms>
  10. <compression xmlns="http://jabber.org/features/compress">
  11. <method>zlib</method>
  12. </compression><auth xmlns="http://jabber.org/features/iq-auth"/>
  13. <register xmlns="http://jabber.org/features/iq-register"/>
  14. </stream:features>

3、客户端发送注册申请

  1. <iq id="69Bxy-0" to="hytest240" type="get">
  2. <query xmlns="jabber:iq:register"></query>
  3. </iq>

4、服务端给出注册需要的填写的信息,相当与给客户端发送一个申请单

  1. <iq type="result" id="69Bxy-0" from="hytest240">
  2. <query xmlns="jabber:iq:register">
  3. <username/><password/><email/><name/>
  4. <x xmlns="jabber:x:data" type="form">
  5. <title>XMPP Client Registration</title>
  6. <instructions>Please provide the following information</instructions>
  7. <field var="FORM_TYPE" type="hidden">
  8. <value>jabber:iq:register</value>
  9. </field>
  10. <field var="username" type="text-single" label="Username">
  11. <required/></field>
  12. <field var="name" type="text-single" label="Full name"/>
  13. <field var="email" type="text-single" label="Email"/>
  14. <field var="password" type="text-private" label="Password">
  15. <required/>
  16. </field>
  17. </x>
  18. </query>
  19. </iq>

5、客户端接收到服务端发送的申请单后,并填写回复:

  1. <iq id="69Bxy-1" to="hytest240" type="set">
  2. <query xmlns="jabber:iq:register">
  3. <username>test</username>
  4. <email></email>
  5. <name></name>
  6. <password>123456</password>
  7. </query>
  8. </iq>

6、注册完成后,服务端返回成功这里没有做出任何消息,仅仅只是回复。

  1. <iq type="result" id="69Bxy-1" from="hytest240" to="hytest240/9fd61155"/>

IQRegisterHandler

IQRegisterHandler位于org.jivesoftware.openfire.handler中。该类主要处理客户端注册信息。

该类中有两个比较重要方法initialize、handleIQ。接下来看这两个方法。

initialize

该方法主要是做初始化注册模板。这个注册模板就是在上面提到的需要发送给客户端申请注册的深表表单。源码如下:

  1. @Override
  2. public void initialize(XMPPServer server) {
  3. super.initialize(server);
  4. userManager = server.getUserManager();
  5. rosterManager = server.getRosterManager();
  6. if (probeResult == null) {
  7. // Create the basic element of the probeResult which contains the basic registration
  8. // information (e.g. username, passoword and email)
  9. probeResult = DocumentHelper.createElement(QName.get("query", "jabber:iq:register"));
  10. probeResult.addElement("username");
  11. probeResult.addElement("password");
  12. probeResult.addElement("email");
  13. probeResult.addElement("name");
  14. // Create the registration form to include in the probeResult. The form will include
  15. // the basic information plus name and visibility of name and email.
  16. // TODO Future versions could allow plugin modules to add new fields to the form
  17. final DataForm registrationForm = new DataForm(DataForm.Type.form);
  18. registrationForm.setTitle("XMPP Client Registration");
  19. registrationForm.addInstruction("Please provide the following information");
  20. final FormField fieldForm = registrationForm.addField();
  21. fieldForm.setVariable("FORM_TYPE");
  22. fieldForm.setType(FormField.Type.hidden);
  23. fieldForm.addValue("jabber:iq:register");
  24. final FormField fieldUser = registrationForm.addField();
  25. fieldUser.setVariable("username");
  26. fieldUser.setType(FormField.Type.text_single);
  27. fieldUser.setLabel("Username");
  28. fieldUser.setRequired(true);
  29. final FormField fieldName = registrationForm.addField();
  30. fieldName.setVariable("name");
  31. fieldName.setType(FormField.Type.text_single);
  32. fieldName.setLabel("Full name");
  33. if (UserManager.getUserProvider().isNameRequired()) {
  34. fieldName.setRequired(true);
  35. }
  36. final FormField fieldMail = registrationForm.addField();
  37. fieldMail.setVariable("email");
  38. fieldMail.setType(FormField.Type.text_single);
  39. fieldMail.setLabel("Email");
  40. if (UserManager.getUserProvider().isEmailRequired()) {
  41. fieldMail.setRequired(true);
  42. }
  43. final FormField fieldPwd = registrationForm.addField();
  44. fieldPwd.setVariable("password");
  45. fieldPwd.setType(FormField.Type.text_private);
  46. fieldPwd.setLabel("Password");
  47. fieldPwd.setRequired(true);
  48. // Add the registration form to the probe result.
  49. probeResult.add(registrationForm.getElement());
  50. }
  51. // See if in-band registration should be enabled (default is true).
  52. registrationEnabled = JiveGlobals.getBooleanProperty("register.inband", true);
  53. // See if users can change their passwords (default is true).
  54. canChangePassword = JiveGlobals.getBooleanProperty("register.password", true);
  55. }

handleIQ

handleIQ方法,方法有四个步骤。

1、判断用户是否已经登陆。如果在session已经存在该用户发送错误消息反馈客户端:

PacketError.Condition.internal_server_error

2、获取IQ消息包的消息类型,如果是type=get那就是客户端需要获取申请表了。然

后,服务端封装这个表单,转成成XMPP消息发送给客户端。

3、当获取到的IQ消息包的消息类型给set(type=set)。那么就是客户点填写完了注册

表单,发送给服务端了。上面描述注册流程的第4步就是提交表单了。源码就不在

贴出来了,这个比较简单。只是一些判断校验比较多。

4、当所有的校验都正确,一切注册流程都正常的话。服务端就该返回第6点消息了。

当然在代码执行过程(业务处理,消息校验等)可能会产生些异常。处理异常的信息

这里把代码贴出来下,大家也可以自己去看源码:

  1. catch (UserAlreadyExistsException e) {
  2. reply = IQ.createResultIQ(packet);
  3. reply.setChildElement(packet.getChildElement().createCopy());
  4. reply.setError(PacketError.Condition.conflict);
  5. }
  6. catch (UserNotFoundException e) {
  7. reply = IQ.createResultIQ(packet);
  8. reply.setChildElement(packet.getChildElement().createCopy());
  9. reply.setError(PacketError.Condition.bad_request);
  10. }
  11. catch (StringprepException e) {
  12. // The specified username is not correct according to the stringprep specs
  13. reply = IQ.createResultIQ(packet);
  14. reply.setChildElement(packet.getChildElement().createCopy());
  15. reply.setError(PacketError.Condition.jid_malformed);
  16. }
  17. catch (IllegalArgumentException e) {
  18. // At least one of the fields passed in is not valid
  19. reply = IQ.createResultIQ(packet);
  20. reply.setChildElement(packet.getChildElement().createCopy());
  21. reply.setError(PacketError.Condition.not_acceptable);
  22. Log.warn(e.getMessage(), e);
  23. }
  24. catch (UnsupportedOperationException e) {
  25. // The User provider is read-only so this operation is not allowed
  26. reply = IQ.createResultIQ(packet);
  27. reply.setChildElement(packet.getChildElement().createCopy());
  28. reply.setError(PacketError.Condition.not_allowed);
  29. }
  30. catch (Exception e) {
  31. // Some unexpected error happened so return an internal_server_error
  32. reply = IQ.createResultIQ(packet);
  33. reply.setChildElement(packet.getChildElement().createCopy());
  34. reply.setError(PacketError.Condition.internal_server_error);
  35. Log.error(e.getMessage(), e);
  36. }

这里出现的PacketError这样的消息包错误对象,在以后的源码中会继续写博客,希望大家多多关照...

注册表单配置

在上面讲解用户注册的流程的时候,相信大家都看到了,用户注册的时候服务端会发送很长的一连串表单要客户端来填写。实际上吗,在openfire官方也不一定确定,世界各地使用注册到底需要哪些属性,所以给出来的注册模板可能会不适合所有的人来使用。那么怎么来修改注册模板呢。

然而在openfire控制管理台,也提供了用户注册表单的配置。在管理台目录:

用户/组->RegistrationProperties这个目录下。截图如下:

Ok,这里面有很多关于注册的使用相关信息。如下几个:

1、RegistrationSettings

2、RegistrationNotification Contacts

3、WelcomeMessage

4、DefaultGroup

5、Sign-Up PageHeader Text

在本章就,本人则挑几个给大家一起分析下。其余的大家可以自己跟踪下源码。

Registration Settings

RegistrationSettings是设置注册配置信息。

这里有禁用使用email,当然也可以添加使用,其他的属性,比如地址,邮编等。

Welcome Message

注册完成后,反馈欢迎词等等。

Default Group

注册完成后,添加到哪些默认组。关于默认组,以后再说。

.......

好了,注册这块就不谈了。

(转)OpenFire源码学习之六:用户注册的更多相关文章

  1. (转)OpenFire源码学习之七:组(用户群)与花名册(用户好友)

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43413651 Group 在openfire中的gorop——组,也可以理解为共享组.什 ...

  2. (转)OpenFire源码学习之二十七:Smack源码解析

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43484199 Smack Smack是一个用于和XMPP服务器通信的类库,由此可以实现即 ...

  3. (转)OpenFire源码学习之十八:IOS离线推送

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43458213 IOS离线推送 场景: 如果您有iOS端的APP,在会话聊天的时候,用户登 ...

  4. (转)OpenFire源码学习之十:连接管理(上)

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43415827 关于连接管理分为上下两部分 连接管理 在大并发环境下,连接资源 需要随着用 ...

  5. (转)OpenFire源码学习之四:openfire的启动流程

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43413233 openfire启动 ServerStarter 启动流程图: 启动的总入 ...

  6. (转)即时通讯IM OpenFire源码学习之三:在Eclipse中构建源码

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43412617 源码搭建 下载地址: 地址:http://www.igniterealti ...

  7. (转)OpenFire源码学习之八:MUC用户聊天室

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43413817 MUC 房间属性设置 以上属性存储在MUCPersistenceManag ...

  8. (转)OpenFire源码学习之十七:HTTP Service插件

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43457645 HTTP Service插件 这里的http接口插件是神马? Openfi ...

  9. (转)OpenFire源码学习之十五:插件开发

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43418493 Plugin接口规范 插件是openfire功能的增强表现,它的主要任务: ...

随机推荐

  1. NetHogs——Linux下按进程实时统计网络带宽利用率

    Debian/Ubuntu下安装很简单,执行:apt-get install nethogs 就可以安装. CentOS/RHEL下建议先安装上EPEL,再执行:yum install libpcap ...

  2. mysql添加索引和sql分析

    mysql索引操作 查看索引 show indexes from students; #students为表名 mysql添加索引命令 创建索引 .PRIMARY KEY(主键索引) mysql> ...

  3. flask中app.py: error: invalid choice: 'insert'........的问题

    在flask中,分为两种操作方式,url指向函数或者终端指向函数,最终目的就是让函数执行,触发方式不同.终端执行更加安全, 另外如果在终端执行的时候出现 : 就是说明 insert 没有在@ mana ...

  4. C语言编译exe添加图标

    C语言是一门通用的计算机编程语言,可以直接编译为可执行文件.在windows下,可执行文件的后缀是exe,我们编写一个最简单的程序test.c: #include <stdlib.h> i ...

  5. client-go获取k8s集群内部连接,实现deployment的增删改查

    一开始写了一个client-java版本的,但是java放在k8s集群上跑需要装jvm而且java的包比较大,client-go版本更适合主机端,下面是整个实现 说明:k8s官方维护的客户端库只有go ...

  6. PouchContainer 容器技术演进助力阿里云原生升级

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 作者 | 杨育兵(沈陵) 阿里巴巴高级技术专家 我们从 2016 年开始在集团推广全面的镜像化容器化,今年是集团全面镜像化容器 ...

  7. %matplotlib inline 被注释掉后,pycharm不能生成图

    目录 问题描述 解决方案 @ 问题描述 在 jupyter 编译器中 程序的开头,有这么一行 %matplotlib inline import numpy as np import matplotl ...

  8. Rust <6>:闭包

    单线程环境: 从宿主环境中捕获的变量,是引用,会改变原有的值,与 golang 的闭包行为一样: 以参数形式传入的变量,默认会发生 move:而 golang 的闭包参数,是宿主环境的副本,相当于在 ...

  9. linux 服务器内存占用统计

    当前内存占用率的计算,是根据top命令显示的Mem.used除以Mem.total得到. Mem.total:表示总物理内存. Mem.used: 表示内核控制的内存数,除了应用程序使用的内存外,还包 ...

  10. HBase优化——读写优化

    Hbase2.0查询优化 1)设置scan缓存 HBase中Scan查询可以设置缓存,方法是setCaching(),这样可以有效的减少服务端与客户端的交互,更有效的提升扫描查询的性能. Scan s ...