(转)OpenFire源码学习之六:用户注册
转:http://blog.csdn.net/huwenfeng_2011/article/details/43413509
用户注册
注册流程:
1、客户端进行握手给服务端发送连接消息:
- <stream:stream to="192.168.2.104" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0"></stream:stream>
2、服务端回执:
- <?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">
- <stream:features>
- <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
- <mechanism>DIGEST-MD5</mechanism>
- <mechanism>JIVE-SHAREDSECRET</mechanism>
- <mechanism>PLAIN</mechanism>
- <mechanism>ANONYMOUS</mechanism>
- <mechanism>CRAM-MD5</mechanism>
- </mechanisms>
- <compression xmlns="http://jabber.org/features/compress">
- <method>zlib</method>
- </compression><auth xmlns="http://jabber.org/features/iq-auth"/>
- <register xmlns="http://jabber.org/features/iq-register"/>
- </stream:features>
3、客户端发送注册申请
- <iq id="69Bxy-0" to="hytest240" type="get">
- <query xmlns="jabber:iq:register"></query>
- </iq>
4、服务端给出注册需要的填写的信息,相当与给客户端发送一个申请单
- <iq type="result" id="69Bxy-0" from="hytest240">
- <query xmlns="jabber:iq:register">
- <username/><password/><email/><name/>
- <x xmlns="jabber:x:data" type="form">
- <title>XMPP Client Registration</title>
- <instructions>Please provide the following information</instructions>
- <field var="FORM_TYPE" type="hidden">
- <value>jabber:iq:register</value>
- </field>
- <field var="username" type="text-single" label="Username">
- <required/></field>
- <field var="name" type="text-single" label="Full name"/>
- <field var="email" type="text-single" label="Email"/>
- <field var="password" type="text-private" label="Password">
- <required/>
- </field>
- </x>
- </query>
- </iq>
5、客户端接收到服务端发送的申请单后,并填写回复:
- <iq id="69Bxy-1" to="hytest240" type="set">
- <query xmlns="jabber:iq:register">
- <username>test</username>
- <email></email>
- <name></name>
- <password>123456</password>
- </query>
- </iq>
6、注册完成后,服务端返回成功这里没有做出任何消息,仅仅只是回复。
- <iq type="result" id="69Bxy-1" from="hytest240" to="hytest240/9fd61155"/>
IQRegisterHandler
IQRegisterHandler位于org.jivesoftware.openfire.handler中。该类主要处理客户端注册信息。
该类中有两个比较重要方法initialize、handleIQ。接下来看这两个方法。
initialize
该方法主要是做初始化注册模板。这个注册模板就是在上面提到的需要发送给客户端申请注册的深表表单。源码如下:
- @Override
- public void initialize(XMPPServer server) {
- super.initialize(server);
- userManager = server.getUserManager();
- rosterManager = server.getRosterManager();
- if (probeResult == null) {
- // Create the basic element of the probeResult which contains the basic registration
- // information (e.g. username, passoword and email)
- probeResult = DocumentHelper.createElement(QName.get("query", "jabber:iq:register"));
- probeResult.addElement("username");
- probeResult.addElement("password");
- probeResult.addElement("email");
- probeResult.addElement("name");
- // Create the registration form to include in the probeResult. The form will include
- // the basic information plus name and visibility of name and email.
- // TODO Future versions could allow plugin modules to add new fields to the form
- final DataForm registrationForm = new DataForm(DataForm.Type.form);
- registrationForm.setTitle("XMPP Client Registration");
- registrationForm.addInstruction("Please provide the following information");
- final FormField fieldForm = registrationForm.addField();
- fieldForm.setVariable("FORM_TYPE");
- fieldForm.setType(FormField.Type.hidden);
- fieldForm.addValue("jabber:iq:register");
- final FormField fieldUser = registrationForm.addField();
- fieldUser.setVariable("username");
- fieldUser.setType(FormField.Type.text_single);
- fieldUser.setLabel("Username");
- fieldUser.setRequired(true);
- final FormField fieldName = registrationForm.addField();
- fieldName.setVariable("name");
- fieldName.setType(FormField.Type.text_single);
- fieldName.setLabel("Full name");
- if (UserManager.getUserProvider().isNameRequired()) {
- fieldName.setRequired(true);
- }
- final FormField fieldMail = registrationForm.addField();
- fieldMail.setVariable("email");
- fieldMail.setType(FormField.Type.text_single);
- fieldMail.setLabel("Email");
- if (UserManager.getUserProvider().isEmailRequired()) {
- fieldMail.setRequired(true);
- }
- final FormField fieldPwd = registrationForm.addField();
- fieldPwd.setVariable("password");
- fieldPwd.setType(FormField.Type.text_private);
- fieldPwd.setLabel("Password");
- fieldPwd.setRequired(true);
- // Add the registration form to the probe result.
- probeResult.add(registrationForm.getElement());
- }
- // See if in-band registration should be enabled (default is true).
- registrationEnabled = JiveGlobals.getBooleanProperty("register.inband", true);
- // See if users can change their passwords (default is true).
- canChangePassword = JiveGlobals.getBooleanProperty("register.password", true);
- }
handleIQ
handleIQ方法,方法有四个步骤。
1、判断用户是否已经登陆。如果在session已经存在该用户发送错误消息反馈客户端:
PacketError.Condition.internal_server_error
2、获取IQ消息包的消息类型,如果是type=get那就是客户端需要获取申请表了。然
后,服务端封装这个表单,转成成XMPP消息发送给客户端。
3、当获取到的IQ消息包的消息类型给set(type=set)。那么就是客户点填写完了注册
表单,发送给服务端了。上面描述注册流程的第4步就是提交表单了。源码就不在
贴出来了,这个比较简单。只是一些判断校验比较多。
4、当所有的校验都正确,一切注册流程都正常的话。服务端就该返回第6点消息了。
当然在代码执行过程(业务处理,消息校验等)可能会产生些异常。处理异常的信息
这里把代码贴出来下,大家也可以自己去看源码:
- catch (UserAlreadyExistsException e) {
- reply = IQ.createResultIQ(packet);
- reply.setChildElement(packet.getChildElement().createCopy());
- reply.setError(PacketError.Condition.conflict);
- }
- catch (UserNotFoundException e) {
- reply = IQ.createResultIQ(packet);
- reply.setChildElement(packet.getChildElement().createCopy());
- reply.setError(PacketError.Condition.bad_request);
- }
- catch (StringprepException e) {
- // The specified username is not correct according to the stringprep specs
- reply = IQ.createResultIQ(packet);
- reply.setChildElement(packet.getChildElement().createCopy());
- reply.setError(PacketError.Condition.jid_malformed);
- }
- catch (IllegalArgumentException e) {
- // At least one of the fields passed in is not valid
- reply = IQ.createResultIQ(packet);
- reply.setChildElement(packet.getChildElement().createCopy());
- reply.setError(PacketError.Condition.not_acceptable);
- Log.warn(e.getMessage(), e);
- }
- catch (UnsupportedOperationException e) {
- // The User provider is read-only so this operation is not allowed
- reply = IQ.createResultIQ(packet);
- reply.setChildElement(packet.getChildElement().createCopy());
- reply.setError(PacketError.Condition.not_allowed);
- }
- catch (Exception e) {
- // Some unexpected error happened so return an internal_server_error
- reply = IQ.createResultIQ(packet);
- reply.setChildElement(packet.getChildElement().createCopy());
- reply.setError(PacketError.Condition.internal_server_error);
- Log.error(e.getMessage(), e);
- }
这里出现的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源码学习之六:用户注册的更多相关文章
- (转)OpenFire源码学习之七:组(用户群)与花名册(用户好友)
转:http://blog.csdn.net/huwenfeng_2011/article/details/43413651 Group 在openfire中的gorop——组,也可以理解为共享组.什 ...
- (转)OpenFire源码学习之二十七:Smack源码解析
转:http://blog.csdn.net/huwenfeng_2011/article/details/43484199 Smack Smack是一个用于和XMPP服务器通信的类库,由此可以实现即 ...
- (转)OpenFire源码学习之十八:IOS离线推送
转:http://blog.csdn.net/huwenfeng_2011/article/details/43458213 IOS离线推送 场景: 如果您有iOS端的APP,在会话聊天的时候,用户登 ...
- (转)OpenFire源码学习之十:连接管理(上)
转:http://blog.csdn.net/huwenfeng_2011/article/details/43415827 关于连接管理分为上下两部分 连接管理 在大并发环境下,连接资源 需要随着用 ...
- (转)OpenFire源码学习之四:openfire的启动流程
转:http://blog.csdn.net/huwenfeng_2011/article/details/43413233 openfire启动 ServerStarter 启动流程图: 启动的总入 ...
- (转)即时通讯IM OpenFire源码学习之三:在Eclipse中构建源码
转:http://blog.csdn.net/huwenfeng_2011/article/details/43412617 源码搭建 下载地址: 地址:http://www.igniterealti ...
- (转)OpenFire源码学习之八:MUC用户聊天室
转:http://blog.csdn.net/huwenfeng_2011/article/details/43413817 MUC 房间属性设置 以上属性存储在MUCPersistenceManag ...
- (转)OpenFire源码学习之十七:HTTP Service插件
转:http://blog.csdn.net/huwenfeng_2011/article/details/43457645 HTTP Service插件 这里的http接口插件是神马? Openfi ...
- (转)OpenFire源码学习之十五:插件开发
转:http://blog.csdn.net/huwenfeng_2011/article/details/43418493 Plugin接口规范 插件是openfire功能的增强表现,它的主要任务: ...
随机推荐
- 深入研究CSS
通常我们在学习CSS的时候,感觉很容易掌握,却常常在实际应用中碰到各式各样难以填补的“坑”,为避免大家受到同样的困惑与不解,本文详细讲解了CSS中优先级和Stacking Context等诸多高级特性 ...
- js的 算法 和 数据结构
js的 算法 1.对一个对象数组按照对象某个属性进行排序 : https://www.cnblogs.com/webcabana/p/7460038.html 在做公交的项目中就碰到过这种算法问题, ...
- 关于自动化测试学习 selenium
selenium学习路线 配置你的测试环境,真对你所学习语言,来配置你相应的selenium 测试环境.selenium 好比定义的语义---“问好”,假如你使用的是中文,为了表术问好,你的写法是“你 ...
- Oracle 用户概念与基本操作
目录 目录 Oracle的用户 通过系统用户来登陆SQLPlus system和sys的区别 查看登陆的用户 启用和锁定一个用户 启用用户 锁定用户 创建用户 修改用户 删除用户 角色权限 常用的用户 ...
- 用cd 命令进入和退出D盘文件夹的操作步骤。
Windows键+R打开运行 输入cmd敲回车,打开命令提示符程序. 输入“cd..”敲回车会退回到上一级目录. 输入“cd\”敲回车会直接退回到C盘根目录 在CMD程序里输入“d:”敲回车可以进入D ...
- Safari的CSS HACK方法
以前的文章里提到过IE6/IE7/IE8/IE9/.Firefox的CSS HACK方法,那么Safari的CSS HACK是什么呢? 请看以下CSS代码: .box { color: black ...
- Javascript优点和缺点
优点: 函数是顶级对象 基于原型继承的动态对象 对象字面量和数组字面量 缺点: 全局变量 作用域 自动插入分号 保留字 Unicode typeof parseInt + 浮点数 NaN
- CF1239
然后ZUTTER_打的第一场div1以没敢交题 完!美!结!束!!! A 没有发现性质就找规律海星 我们可以算出一列的贡献:\(g[i][0]\)表示上两个不同,\(g[i][1]\)表示上两个相同就 ...
- mysql-视图及索引简介
一.视图的创建.作用及注意事项 1.创建:create view 视图名 as select 语句: 2.删除:drop view 视图名 3.作用: 数据库视图允许简化复杂查询 数据库视图有助于限制 ...
- Jmeter请求非Json格式的参数如何添加
Step1: 可以先在用户自定义变量中加入你需要添加的请求类型,具体参考图片 Step2: 在线程组下请求之前添加HTTP信息头管理器