转: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. hdu1574 I Hate It (线段树,查询区间最大值)

    Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟 ...

  2. 高级运维(七):Subversion基本操作、使用Subversion协同工作、制作nginx的RPM包

    一.Subversion基本操作 目标: 本案例要求先快速搭建好一台Subversion服务器,并测试该版本控制软件: 1> 创建版本库    2> 导入初始化数据    3> 检出 ...

  3. restTemplate源码详解深入剖析底层实现思路

    一 准备工作 1 启动一个项目,发布一个restful的get请求,端口设置为8090. @RestController @RequestMapping("/youku1327") ...

  4. 81、Tensorflow实现LeNet-5模型,多层卷积层,识别mnist数据集

    ''' Created on 2017年4月22日 @author: weizhen ''' import os import tensorflow as tf import numpy as np ...

  5. python requests方法post请求json格式处理

    方法如下: import requestsimport json data = {    'a': 123,    'b': 456} ## headers中添加上content-type这个参数,指 ...

  6. Redis Sentinel用法

    1 Redis Sentinel 1.1 哨兵的作用 1. 监控:监控主从是否正常 2. 通知:出现问题时,可以通知相关人员 3. 故障迁移:自动主从切换 4. 统一的配置管理:连接者询问sentin ...

  7. vbox出现Failed to opencreate the internal network错误,无法启动虚拟机

    vbox出现Failed to opencreate the internal network错误,无法启动虚拟机 标签(空格分隔): 未分类 问题 Failed to open/create the ...

  8. 基于MFC的Media Player播放器的控件方法和属性介绍

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 因为使用第三方多媒体库或是第三方控件(Media Player)辅助播放,我们则必须要了解到Media Player控件的一些属性 和方法 ...

  9. python面试题之下面这些是什么意思:@classmethod, @staticmethod, @property?

    回答背景知识 这些都是装饰器(decorator).装饰器是一种特殊的函数,要么接受函数作为输入参数,并返回一个函数,要么接受一个类作为输入参数,并返回一个类. @标记是语法糖(syntactic s ...

  10. 导出CSV格式

    import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype. ...