jabber协议中如何注册一个用户?
首先要与服务器建立一个连接, 在完成TLS握手之后就可以进行注册了,为什么不需要SASL握手呢?因为SASL握手只针对已经注册的用户在登陆服务器的时候使用.(修改密码和删除用户的时候需要SASL握手)
下面以openfire作为服务器,注册一个用户的过程如下:
(假设已经完成了TLS握手)
1. ( C->S )
<stream:stream
to='ziz-wrks-tfsxp1'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
xml:lang='en'
version='1.0'>
TLS握手结束后, 发送新的'hello'消息
2. ( S->C )
<stream:stream
xmlns:stream='http://etherx.jabber.org/streams'
xmlns='jabber:client'
from='ziz-wrks-tfsxp1'
id='b691538a'
xml:lang='en' version='1.0'/>
Server回应Client的hello消息.
3. ( S->C )
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</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>
服务器支持的features(可以register)
4. ( C->S )
<iq type='get' id='uid1'>
<query xmlns='jabber:iq:register'/>
</iq>
客户端请求注册
5. ( S->C )
<iq type='result' id='uid1'>
<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 label='Username' var='username' type='text-single'>
<required/>
</field>
<field label='Full name' var='name' type='text-single'/>
<field label='Email' var='email' type='text-single'/>
<field label='Password' var='password' type='text-private'>
<required/>
</field>
</x>
</query>
</iq>
服务器返回注册需要的fields
(其中元素x里面的数据是扩展性的数据表但,暂时忽略)
6. ( C->S )
<iq id='uid2' type='set'>
<query xmlns='jabber:iq:register'>
<username>user3</username>
<password>user@123</password>
<name/>
<email/>
</query>
</iq>
用户提交注册信息.
7. ( S->C )
<iq type='result' id='uid2' to='ziz-wrks-tfsxp1/b691538a'/>
服务器返回注册结果
#如何更改用户密码
更改用户密码必须在完成与服务器的链接之后才能进行,也就是完成与服务器的TLS,SASl握手之后
再进行.
1. ( C->S )
<iq type='set' id='uid3'>
<query xmlns='jabber:iq:register'>
<username>user23</username>
<password>123456</password>
</query>
</iq>
发送更改密码的请求
2. ( S->C )
<iq type='result' id='uid3' to='user23@ziz-wrks-tfsxp1/2f21fd1f'/>
返回处理结果(操作成功)
#如何注销一个用户
注销一个用户必须在完成与服务器的链接之后才能进行,也就是完成与服务器的TLS,SASl握手之后
再进行.
1. ( C->S )
<iq type='set' id='uid3' from='testuser@ziz-wrks-tfsxp1/3a418274'>
<query xmlns='jabber:iq:register'><remove/></query>
</iq>
发送注销用户的请求
2. ( S->S )
<iq type='result' id='uid3' to='testuser@ziz-wrks-tfsxp1/3a418274'/>
返回处理结果(注销成功)
总结:
注册用户和更改或者注销用户的一个区别就是注册用户不需要经过SASL握手,而更改和注销用户需要.
也就是需要对用户身份进行验证.
gloox的注册模块
registration.h
registration.cpp
registrationhandler.h
就是对上述协议的封装,方便创建register stanza,并把收到的消息分发到相应的handler方法.
gloox的client是如何处理xml流的呢?
1. 连接到服务器后,使客户端进入"receive mode",可以循环的接收数据.
2. 数据流 [接收到的数据 handleReceiveData() ] -> [解析xml数据流,解析成不同的tag, parser()] -> [ 触发handleTag(), 针对不同的tag分发到不同的handlers做不同的处理 ]
- stream:stream - ...
- stream:error - ...
- Iq - IqHandler
- Presence - presenceHandler
- Message - messageHandler
Iq消息的处理机制,以及trackID机制:
实质上registration是一个Iqhandler, 它实现的是handleIqID( Stanza *stanza, int context )接口,而不是handleIq( Stanza *stanza )接口,其中context实质上为iqHandler具体实现中的子操作类型,在registration中分别为 fetchRegisterFiled, createAccount, changePassword, removeAccount.
对一个Iq Stanza的处理方式可以通过一般的IqHandler - xmlnamespace filer或者IqHandler - TrackID机制来处理.
下面代码展示了如何注册/修改密码/删除用户(服务器是openfire):
1#include <iostream>
2#include "registration.h" // gloox headers
3#include "client.h"
4#include "connectionlistener.h"
5#include "logsink.h"
6#include "loghandler.h"
7
8#pragma comment( lib, "gloox.lib" )
9using namespace gloox;
10
11#define SERVERNAME "xxxxxx"
12#define HEADERTO "xxxxxx"
13
14#define USERNAME "user123"
15#define PASSWORD "user@123"
16#define NEWPASSWORD "123456"
17
18//
19// three scenario3
20// 1 - register user (Note: don't need SASL handshake)
21// 2 - change password (Note: need SASL handshake)
22// 3 - delete user (Note: need SASL handshake)
23//
24class RegisterImpl : public RegistrationHandler, ConnectionListener, LogHandler {
25public:
26 void run();
27
28 //implement RegistrationHandler
29 void handleRegistrationFields( const JID& from, int fields, std::string instructions );
30 void handleAlreadyRegistered( const JID& from );
31 void handleRegistrationResult( const JID& from, RegistrationResult regResult );
32 void handleDataForm( const JID& from, const DataForm &form );
33 void handleOOB( const JID& from, const OOB& oob );
34
35 //implement ConnectionListener
36 void onConnect();
37 void onDisconnect( ConnectionError e );
38 void onResourceBindError( ResourceBindError error );
39 void onSessionCreateError( SessionCreateError error );
40 bool onTLSConnect( const CertInfo& info );
41 void onStreamEvent( StreamEvent event );
42
43 //implement LogHandler
44 void handleLog( LogLevel level, LogArea area, const std::string& message );
45
46private:
47 Registration* register_;
48 Client* client_;
49};
50
51void RegisterImpl::run() {
52 client_ = new Client(SERVERNAME);
53 client_->setHeaderTo(HEADERTO);
54 client_->registerConnectionListener(this);
55 register_ = new Registration( client_ );
56 register_->registerRegistrationHandler( this );
57 client_->logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, this );
58
59 // run scenario2 and scenario3 need enable username and
60 // password to run SASL, scenario1 did not need.
61 client_->setUsername(USERNAME);
62 client_->setPassword(PASSWORD);
63
64 client_->connect();
65
66 delete register_;
67 delete client_;
68}
69
70void RegisterImpl::handleRegistrationFields( const JID& from, int fields, std::string instructions ) {
71 // register account
72 std::cout<<"impl# register instruction: "<<instructions<<std::endl;
73 RegistrationFields vals;
74 vals.username = USERNAME;
75 vals.password = PASSWORD;
76 register_->createAccount( fields, vals );
77}
78
79void RegisterImpl::handleAlreadyRegistered( const JID& from ) {
80 std::cout<<"impl# the count already exists."<<std::endl;
81}
82
83void RegisterImpl::handleRegistrationResult( const JID& from, RegistrationResult regResult ) {
84 if( regResult == RegistrationSuccess ) {
85 std::cout<<"impl# operation success."<<std::endl;
86 } else {
87 std::cout<<"impl# operation failed."<<std::endl;
88 }
89
90 client_->disconnect();
91}
92
93void RegisterImpl::handleDataForm( const JID& from, const DataForm &form ) {
94 //TODO:
95}
96
97void RegisterImpl::handleOOB( const JID& from, const OOB& oob ) {
98 //TODO:
99}
100
101void RegisterImpl::onConnect() {
102 std::cout<<"impl# connect to server success."<<std::endl;
103 //operation
104
105 // scenario1 - register
106 // this will invoke handleRegistrationResult() to createAccount
107 // Note: doesn't need SASL handshake
108 register_->fetchRegistrationFields();
109
110 // scenario2 - change password
111 // Note: need SASL handshake, in gloox, set the username & password in clientbase, will
112 // run the SASL handshake.
113 // register_->changePassword( client_->username(), NEWPASSWORD );
114
115 // scenario3 - delete account
116 // Note: need SASL handshake,
117 // register_->removeAccount();
118}
119
120void RegisterImpl::onDisconnect( ConnectionError e ) {
121 std::cout<<"impl# disconnected."<<std::endl;
122}
123
124void RegisterImpl::onResourceBindError( ResourceBindError error ) {
125 //TODO:
126}
127
128void RegisterImpl::onSessionCreateError( SessionCreateError error ) {
129 //TODO:
130}
131
132bool RegisterImpl::onTLSConnect( const CertInfo& info ) {
133 std::cout<<"impl# tls connect to server success."<<std::endl;
134 return true;
135}
136
137void RegisterImpl::onStreamEvent( StreamEvent event ) {
138 //TODO:
139}
140
141void RegisterImpl::handleLog( LogLevel level, LogArea area, const std::string& message ) {
142 std::cout<<"impl-log# "<<message<<std::endl;
143}
144
145int main( int argc, char* argv[] ) {
146 RegisterImpl impl;
147 impl.run();
148 return 0;
149}
posted on 2008-11-06 12:59 ysong.lee 阅读(1106) 评论(3) 编辑 收藏 引用
Feedback
# re: gloox代码分析3 - 注册模块 2008-11-14 19:09 ly
hao 回复 更多评论
# re: gloox代码分析3 - 注册模块 2008-11-14 19:13 ly
client_->setHeaderTo(HEADERTO);
错误提示在client 里找不到setHeaderTo?????什么问题?
我把你这句去掉后,改成
client_->disableRoster();
发现能注册成功,但是,登陆提示:sasl failed。
登陆不成功!~~~什么原因~~~望解答!~~ 回复 更多评论
# re: gloox代码分析3 - 注册模块 2008-11-18 13:01 ysong.lee
1. 我对gloox进行了修改,client_->setHeaderTo(HEADERTO); 是自己添加的方法,目的是为了fix gloox不能连接到gtalk server的问题,通过修改,可以自己控制ClientBase::header()方法中在发送hello信息时候的to属性,这在服务器是 gtalk server的时候是有用的,如果我们的服务器地址设置为talk.google.com,则header()方法默认to= "talk.google.com",这是错误的,应该为to="gmail.com".
2. sasl failed。登陆的时候需要sasl 验证,如果服务器为gtalk server, 当你接收到服务器发送的以下信息的时候
(Server -> Client)
<stream:features>
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>PLAIN</mechanism>
<mechanism>X-GOOGLE-TOKEN</mechanism>
</mechanisms>
</stream:features>
需要进行sasl验证,发送的验证数据格式为:
'/0'+username+'/0'+password 的base64编码, username和password必须是经过认证的.
例如:
'/0' + 'ysong.lee@gmail.com' + '/0' + 123456 -> 经过base64编码处理
(Client -> Server)
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">
AHlzb25nLmxlZUBnbWFpbC5jb20AeXNvbmdAMTk4NA==
</auth>
相关推荐
DataWorks PyODPS第三方包全攻略:从打包到加载的完整流程
本文详细介绍了在DataWorks的PyODPS节点中使用第三方Python包的完整流程,包括环境限制、打包工具pyodps-pack的使用、资源上传与加载实战,以及特殊场景处理技巧。通过本文,开发者可以掌握在MaxCompute受限环境中灵活使用自定义依赖的方法,提升数据处理效率。
(转)OpenFire源码学习之六:用户注册
转:http://blog.youkuaiyun.com/huwenfeng_2011/article/details/43413509 用户注册 注册流程: 1、客户端进行握手给服务端发送连接消息: [html]view plaincopy <stream:streamto="192.168.2.104"xmlns="jabber:clien...
MacOS新手必看:HomeBrew安装避坑指南(含M1芯片适配方案)
本文为MacOS新手提供全面的HomeBrew安装指南,特别包含M1/M2芯片适配方案。从系统准备到核心安装流程,再到日常维护和高级配置,详细解析每个步骤的潜在问题及解决方案,帮助用户高效管理Mac软件。
gloox开发
1、服务器环境 服务器是在xp系统下安装的(我是在虚拟机中的xp系统下安装的),服务器采用的是Openfire 3.9.3版本,安装服务器时采用的是服务器自带的数据库。 2、编程环境 编程环境是在win7 64位系统下进行的,采用的是Microsoft Visual Studio 2010 旗舰版进行编程。 3、客户端编程采用的技术 3.1采用基于C++实现的XMPP协议客户端开源库gloox gloox简介: gloox是一个开源的跨平台的C++实现的XMPP协议开发包,目前的版本为1.0.
光模块基础知识【快速入门】02
光模块是用于交换机与设备之间传输的载体,是光纤通信系统中的核心器件。主要作用是发射端将设备的电信号转换成光信号。 光纤通道光模块和以太网光模块 光纤通道光模块 光纤通道(FC, Fiber Channel)是一种高速网络数据传输协议。光纤通道协议可以有序无损地传输原始数据,它主要用于在数据中心、电脑服务器、交换机与存储网络中进行数据传输。 FC光模块遵循FC协议,充当着光纤通道系统之间的接口,也是光纤存储网络设备间的接口。它们主要用于数据中心的光纤通道存储网络链接中。 FC光模块具有小型化和低.
卡尔曼滤波原理详解及系统模型建立(simulink)
卡尔曼滤波原理详解及系统模型建立(simulink) 卡尔曼滤波器 卡尔曼滤波器是在上个世界五六十年代的时候提出的,到今天已经有六十年左右的时间,但卡尔曼滤波算法不管在控制、制导、导航或者通讯方面对数据的预测能力依然处在一个不可撼动的位置上,但是很多人对于其算法内部的工作原理究竟是怎么运作的依然不理解,所以在工程上很多人都只是把卡尔曼滤波当成是一种“黑箱”预测算法,并不清楚内部原理。但实际上没有任...
Jabber 协议 概述(2)
6.11. jabber:iq:register——注册请求<br />注册请求名字空间对一个或多个服务进行注册。它也被用来更新或删除一个注册。<br />例子:<br /><query xmlns="jabber:iq:register"><br /><instructions><br />Some instructions to be displayed when the<br />user is filling out the form.<br /></instructions><br /><user
【系统架构设计师-2023年真题】综合知识-答案及详解
要实现多任务间的协同工作,操作系统必须提供任务间的通信手段。嵌入式操作系统一般都会提供多任务间通信的方法,其中()是任务间最直接、最明显的通信方法,也是访问共享的数据结构,即不同的任务都可以访问同一地址空间。()作为一种更高级的通信方式,能够在同一处理器的各个任务间传递任意长度(理论上只受物理内存和机器字长限制)的信息。(1)A. 共享内存 B. Socket C. 消息传递 D. 信号量(2)A. 共享内存 B. Socket C. 消息传递 D. 信号量【答案】A、C关于星型拓扑结构,下列说法正确的是(
Jabber 注册一个新用户的流程(JabberD + gloox)
从网络实际发送,接收到的包来分析Jabber协议中注册一个新用户的过程例子服务器所用的是 JabberD2 S7版 客户端是 gloox 0.8版的注册测试程序用其它的服务器和客户端,可能会有所不同,但大体上应该是一样的C->S 001xmlns=jabber:clientxmlns:stream=http://etherx.jabber.org/streams xml:lang=en
新能源汽车动力总成研发测试技术全景深度报告(2025版)
本文所有企业案例数据均来自上市公司财报、工信部备案信息及权威媒体报道,技术参数经第三方检测报告交叉验证。研发测试人员能力矩阵重构(T型人才进阶路径)[10] 全球动力总成市场2035年预测报告。[9] NI电动汽车HIL测试架构技术文档。[3] 东风汽车智能化研发体系深度报告。[5] 混合动力测功机发明专利技术细节。[1] 领克动力总成试验中心技术解析。[7] 新能源汽车产业迭代趋势白皮书。测试架构师-数字工程。测试架构师-安全合规。测试架构师-人工智能。
[Python图像处理] 十.形态学之图像顶帽运算和黑帽运算
数学形态学(Mathematical morphology)是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论。其基本的运算包括:腐蚀和膨胀、开运算和闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换等。本篇文章主要讲解Python调用OpenCV实现图像形态学转化,包括图像顶帽运算和图像黑帽运算,基础性知识希望对您有所帮助。
Python全栈入门到实战【基础篇 22】生成器与迭代器:底层逻辑与实战场景
Python迭代器与生成器:惰性求值的高效实践 摘要:本文深入解析Python中迭代器和生成器的核心机制与应用场景。迭代器通过实现__iter__()和__next__()方法实现惰性求值,适合处理大数据集和无限序列。生成器作为迭代器的简化实现,通过yield关键字自动实现迭代器协议,代码更简洁。文章详细对比了可迭代对象与迭代器的区别,演示了自定义迭代器和生成器函数的实现方式,并介绍了生成器表达式这一高效替代列表推导式的方案。通过斐波那契数列等实例,展示了惰性求值在内存优化方面的优势,以及生成器在流式数据处
gloox代码分析 - 注册模块(摘抄)
#jabber协议中如何注册一个用户?首先要与服务器建立一个连接, 在完成TLS握手之后就可以进行注册了,为什么不需要SASL握手呢?因为SASL握手只针对已经注册的用户在登陆服务器的时候使用.(修改密码和删除用户的时候需要SASL握手)下面以openfire作为服务器,注册一个用户的过程如下:(假设已经完成了TLS握手)1. ( C->S ) to=ziz-wrks-tfsxp1
ET2012新版免狗免安装绿色软件
ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,
华为的C语言编程规范.pdf
华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。
gloox注册、登录、登出、消息收发的实现(IM客户端)
Gloox的资料实在太少,官方包里有example,但每个用法示例的注释也没有。在反复阅读example下的代码,组合,基本实现了用户的注册、登录、登出 以及 消息的发送与接受。主要参考 register_example.cpp 与 message_example.cpp 封装了一个类Gloox Gloox.h#ifndef GLOOX_H #define GLOOX_H#include "glo
计算机控制技术及应用
《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。
注册模块的错误解决
今天在弄注册模块的时候发现注册不了,,为了方便直接用了openfire。。然后问题就来 了,return错误码为4------RegistrationBadRequest;百度了下,找到解决的办法如下: 对于GLOOX自带的注册例子不能正常注册的问题有人在邮件列表里提出来。一个哥们这样回答: [plain] view plaincopy Ok,
老版QQ原生表情gif动态
这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。
GLOOX 1.0---注册模块
改定履历 2011-09-09---------------------新建文本文档 引文: 调试GLOOX 1.0的注册功能颇费了一些功夫。总体逻辑如GLOOX自带的例子一样是毫无疑问的,但是照搬例子又是不能完成注册的,返回错误码为4------RegistrationBadRequest。笔者一开始在网上狂搜解决方案,资料少之又少,有建议重写Client::handleNorma
Gloox 注册用户
改定履历 2011-09-09---------------------新建文本文档 引文: 调试GLOOX 1.0的注册功能颇费了一些功夫。总体逻辑如GLOOX自带的例子一样是毫无疑问的,但是照搬例子又是不能完成注册的,返回错误码为4------RegistrationBadRequest。笔者一开始在网上狂搜解决方案,资料少之又少,有建议重写Client::han
gloox1.0中注册账号不成功的问题
前段时间研究gloox1.0版的注册,用官方自带的example,注册应该是很简单的例子,代码如下: 1: j = new Client( "pc-20110409pvwc" ); 2: j->disableRoster(); 3: j->registerConnectionListener( this ); 4: 5: m_reg = new Registration( j
gloox连接至服务器端
在使用gloox之前,有必要先提一下XMPP协议这个东东。XMPP协议是一个基于互联网的即时通信标准协议。它采用XML技术,以文本的方式传输即时消息。支持动态自定义扩展应用。与传统的网络协议相比,如QQ等,XMPP协议并不是一个基于二进制方式实现的协议,而是基于XML技术的文本方式,也就是说如果不采用加密技术的话,是可以直接查看发送的消息的。XMPP协议通过定义一些XML的节点关键字,来表明消
gloox连接xmpp服务器
先从官网下载gloox的压缩包。 下载地址:http://camaya.net/glooxd/download/ 因为gloox是个c++的库,所以我用的是visual studio 2013编译的,以下是主要步骤: 新建项目32位应用控制台程序->选择空文件的控制台程序,把预编译头去掉。生成了解决方案,,鼠标右键添加新建筛选器,命名gloox,然后把官网下载好的gloox压缩
gloox不能注册新用户的问题
经过测试,发现gloox 0.8版自带的测试程序register_test.cpp,是没有办法注册新用户的前面的三步是这样没错Client->Server 001xmlns=jabber:clientxmlns:stream=http://etherx.jabber.org/streams xml:lang=en version=1.0>客户端向服务器建立连接,version=1
给gloox加上支持接收好友更新头像的信息
项目需要,可能实现的有点麻烦,大家如果有好方法,请告诉我! 在gloox库的基础上,要实现的功能: 当好友头像信息修改后(vcard),本地立即去获取好友头像。 1、增加一个头文件:VCardUpdateHandler.h 用来接收好友头像变更消息 class VCardUpdateHandler { public: virtual ~VCardUpdateHandler()
gloox 之 MainPage
<br />本文章转载与http://hi.baidu.com/ln5336993/blog/item/54fa8d283e31d3ea98250adb.html<br />gloox mainPage:http://camaya.net/api/gloox-1.0/index.html<br />前言gloox库是按照“观察者”模式设计的,意思就是说一切都是事件驱动的。使用gloox有两种方法可以连接到Jabber/XMPP网络,它们是客户端或组件。第三种是作为服务器,但是gloox不支持,尽管某些方面支
989



被折叠的 条评论
为什么被折叠?



