(转)OpenFire源码学习之六:用户注册

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

用户注册

注册流程:

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

[html] view plain copy

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

2、服务端回执:

[html] view plain copy

  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、客户端发送注册申请

[html] view plain copy

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

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

[html] view plain copy

  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、客户端接收到服务端发送的申请单后,并填写回复:

[html] view plain copy

  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、注册完成后,服务端返回成功这里没有做出任何消息,仅仅只是回复。

[html] view plain copy

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

IQRegisterHandler

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

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

initialize

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

[java] view plain copy

  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点消息了。

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

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

[java] view plain copy

  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

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

.......

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

时间: 2024-08-12 12:05:57

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

OpenFire源码学习之三:在Eclipse中构建源码

源码搭建 下载地址: 地址:http://www.igniterealtime.org/downloads/source.jsp 环境准备 第1步:  在官网上在下最新源码,这里是3.8.1.解压后得到如下图所示: 第2 步: 在IDE工具上新建一个java普通工程命名openfire 第3步: 将解压后的openfire_src目录的下的所有文件源码复制到此项目下,例图所示 这里稍等片刻后,看到如下效果图: 上图中在工程上出现了错误信息报告,不用着急.原因是刚导入的项目还有些jar包没有加进来

OpenFire源码学习之四:openfire的启动流程

openfire启动 ServerStarter 启动流程图: 启动的总入口在ServerStarter的main方法中.通过上图首先它会先加载它所需要的jar文件.最后通过java反射机制将XMPPServer加入当前线程. Thread.currentThread().setContextClassLoader(loader); Class containerClass = loader.loadClass( "org.jivesoftware.openfire.XMPPServer&quo

OpenFire源码学习之十八:IOS离线推送

IOS离线推送 场景: 如果您有IOS端的APP,在会话聊天的时候,用户登陆了但可能会退出了界面.这时候其他终端给目标端发送消息时候,消息可以发送到IOS的推送服务器.用过QQ的都知道,你会有哦一条消息在您的主屏上展示.这个就是利用了IOS的推送服务器呢.那么openfire只需要判断用户不在线的时候将消息推送给IOS端. 苹果服务器的消息推送都需要手机的唯一标志,也就是唯一的终端设备号.那么IOS端在登陆的时候需要将该手机的设备号传递给OF服务器.这个传递很简单,您可以自定义发送IQ消息.也可

OpenFire源码学习之十九:在openfire中使用redis插件(上)

Redis插件 介绍 Redis是目前比较流行的NO-SQL,基于K,V的数据库系统.关于它的相关操作信息,本人这里就不做重复了,相关资料可以看这个网站http://www.redis.io/(官网).http://www.redis.cn/(中文站). 这里本人想说的是,拿Redis做openfire的缓存数据库.能够大大的提高openfire连接的吞吐量.Openfire自身在本地使用Map.Cache的方式缓存了Group.roster.MUC等信息.但是当系统用户过大的时候,需要缓存的数

OpenFire源码学习之二十:在openfire中使用redis插件(下)

Redis插件实现 首先来看下插件目录: RedisServicePlugin 源码清单: import java.io.File; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.jivesoftware.database.DbConnecti

OpenFire源码学习之二十一:openfie对用户的优化(上)

用户类 优化用户主要是要解决用户的连接量.已经对用户的访问速度和吞吐量. 预初始化 在前面的带面中提出来了用户的预初始化.这里就不在贴出来了.下面将redis用户库连接池处理贴出来UserJedisPoolManager public class UserJedisPoolManager extends BasicModule{ private static final Logger log = LoggerFactory.getLogger(UserJedisPoolManager.class

OpenFire源码学习之二十三:关于消息的优化处理

消息处理 之前有说过,openfire的消息处理策略本人并不是很喜欢.先看下openfire上脱机消息策略. 个人认为消息关于会话的消息,用户的存储量应该无限大.服务器不应该被消息吃撑了.所谓聊天通讯,这一关很重要. Openfire的消息是什么流程呢. 1.当用户登陆连接的时候.握手.认证.绑定资源.获取花名册.获取离线消息. 2.服务端会查找关系型数据库.经本人测试离线消息在数据库表中达到100万条以上的时候,查询速度非常慢,甚至会导致openfire奔溃. ..... 那么openfire

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

转:http://blog.csdn.net/huwenfeng_2011/article/details/43415827 关于连接管理分为上下两部分 连接管理 在大并发环境下,连接资源 需要随着用户并发访问量的增加而增加,所以可伸缩的连接资源就是支持大访问量的关键技术.openfire系统通过增加独立部署的连接管理器程序提高并发的能力,连接管理的前端是一台负载均衡设备,它负责把用户访问分配到指定连接管理器,多台连接管理器在访问服务器.使用连接管理器后,服务器的连接池是提供给连接管理器连 接,

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

转:http://blog.csdn.net/huwenfeng_2011/article/details/43413233 openfire启动 ServerStarter 启动流程图: 启动的总入口在ServerStarter的main方法中.通过上图首先它会先加载它所需要的jar文件.最后通过Java反射机制将XMPPServer加入当前线程. [java] view plain copy Thread.currentThread().setContextClassLoader(loade