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

登陆

登陆认证,客户端发送认SASL证消息:

  1. <auth mechanism="DIGEST-MD5" xmlns="urn:ietf:params:xml:ns:xmpp-sasl"></auth>

服务器得到客户端给出的SASL认证机制回答。首先将它存储起来。

C给出的认证机制为DIGEST-MD5,又服务器发起盘问。

  1. <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
  2. cmVhbG09IjhudG1vcnYxZXA0d2djeSIsbm9uY2U9InpydUNlS000YXJQU3N3Tm1MVFRacFdNWEdrYUdQQlhqdGZVY3ZRbXoiLHFvcD0iYXV0aCIsY2hhcnNldD11dGYtOCxhbGdvcml0aG09bWQ1LXNlc3M=
  3. </challenge>

既然服务器发出了盘问,客户端自然需要返回回答了,下面是客户端回答的内容

  1. <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
  2. Y2hhcnNldD11dGYtOCx1c2VybmFtZT0idGVzdDEiLHJlYWxtPSI4bnRtb3J2MWVwNHdnY3kiLG5vbmNlPSJ6cnVDZUtNNGFyUFNzd05tTFRUWnBXTVhHa2FHUEJYanRmVWN2UW16IixuYz0wMDAwMDAwMSxjbm9uY2U9Ik9DZ1cyb2ZsajVDN0I1TUc1MVFZQXRYcnRHbitGR1hxaW1Uc01vbG0iLGRpZ2VzdC11cmk9InhtcHAvOG50bW9ydjFlcDR3Z2N5IixtYXhidWY9NjU1MzYscmVzcG9uc2U9NTNhNTJkNjE0M2Q5ZjUwMzNkYmRhOWRkYmUwMDBhYTUscW9wPWF1dGgsYXV0aHppZD0idGVzdDEi
  3. </response>

不知道这一问一答,问的是什么内容。应该就是用户名密码校验了。不管怎样,客户端回答是正确的。应该是个用户名的加密字符串吧。

在这个过程中 查找用户的可用性,先将从缓存lockOutCache中查找。根据最近登陆时间段,查找用户是否已经存在,如果不存在,就从数据中查找

  1. SELECT name,startTime,endTime FROM ofUserFlag WHERE username=? AND name='lockout'

既然客户端回答正确,那么服务端又怎么作答呢?

  1. <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
  2. cnNwYXV0aD1lNWIzYjJkMjk1NjRmMTIxNDEwOWRmZTA5MTIzNDk2Nw==
  3. </success>

告知回答成功

SASL认证成功,设置本地客户端认证内容

  1. if (session instanceof ClientSession) {
  2. ((LocalClientSession) session).setAuthToken(new AuthToken(username));

这是认证成功了。

如果认证失败,很简单服务器直接关闭了会话:

  1. private static void authenticationFailed(LocalSession session) {
  2. StringBuilder reply = new StringBuilder(80);
  3. reply.append("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
  4. reply.append("<not-authorized/></failure>");
  5. session.deliverRawText(reply.toString());
  6. // Give a number of retries before closing the connection
  7. Integer retries = (Integer) session.getSessionData("authRetries");
  8. if (retries == null) {
  9. retries = 1;
  10. }
  11. else {
  12. retries = retries + 1;
  13. }
  14. session.setSessionData("authRetries", retries);
  15. if (retries >= JiveGlobals.getIntProperty("xmpp.auth.retries", 3) ) {
  16. // Close the connection
  17. session.close();
  18. }
  19. }

这一段会话结束,客户端发送消息:

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

因为客户端已经认证成功,服务端就又打开一个新的流,并提供新的流功能,如资源约束和会话建立。请注意,资源约束和会话建立应该只提供给客户(即不用于服务器或外部元件)

以下是服务器邀请绑定资源:

  1. <?xml version='1.0' encoding='UTF-8'?>
  2. <stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="8ntmorv1ep4wgcy" id="2884481a"
  3. xml:lang="en"
  4. version="1.0">
  5. <stream:features>
  6. <compression xmlns="http://jabber.org/features/compress">
  7. <method>zlib</method>
  8. </compression>
  9. <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
  10. <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
  11. </stream:features>

Ok,既然服务器发送资源绑定邀请了。看下客户端发送的内容吧:

  1. <iq id="wSBRk-4" type="set">
  2. <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
  3. <resource>Smack</resource>
  4. <terminal>android</terminal>
  5. </bind>
  6. </iq>

IQ设置resorcr节点为资源内容

Terminal是本人自己加上的资源终端标识码。

在服务服端,关于IQHandler的子类有很多,当服务器接收到了绑定的请求。处理会交给

IQBindHandler来处理。

节点+域+资源+标识组成了新的JID。通过JID从本地路由中查找的会话是否存在。

如果存在,会刷出错误。这时候让客户端选择是否继续。

当然,这里登陆并没有冲突。我们继续!

没有存在其他的会话后,开始设置有效的身份验证令牌和资源名称初始化会话。这会自动升级会话的状态,以通过身份验证,使许多功能,直到认证(获得经理为例)不可用。

  1. public void setAuthToken(AuthToken auth, String resource, String terminal) {
  2. setAddress(new JID(auth.getUsername(), getServerName(), resource, terminal));
  3. authToken = auth;
  4. setStatus(Session.STATUS_AUTHENTICATED);
  5. // Set default privacy list for this session
  6. setDefaultList(PrivacyListManager.getInstance().getDefaultPrivacyList(auth.getUsername()));
  7. // Add session to the session manager. The session will be added to the routing table as well
  8. sessionManager.addSession(this);
  9. }

第一先设置地址

设置会话状态为3

设置用于会话的用户的默认隐私列表。如果没有活动列表为会话设置该列表被处理。

最后,添加一个新的会话来进行管理。该会话已经通过认证和资源约束已经完成。

  1. public void addSession(LocalClientSession session) {
  2. // Remove the pre-Authenticated session but remember to use the temporary ID as the key
  3. localSessionManager.getPreAuthenticatedSessions().remove(session.getStreamID().toString());
  4. // Add session to the routing table (routing table will know session is not available yet)
  5. routingTable.addClientRoute(session.getAddress(), session);
  6. SessionEventDispatcher.EventType event = session.getAuthToken().isAnonymous() ?
  7. SessionEventDispatcher.EventType.anonymous_session_created :
  8. SessionEventDispatcher.EventType.session_created;
  9. // Fire session created event.
  10. SessionEventDispatcher.dispatchEvent(session, event);
  11. if (ClusterManager.isClusteringStarted()) {
  12. // Track information about the session and share it with other cluster nodes
  13. sessionInfoCache.put(session.getAddress().toString(), new ClientSessionInfo(session));
  14. }
  15. }

好了,到了这个过程。绑定资源过程结束了。系统返回一个完成操作的报告给客户端。看下内容:

  1. <iq type="result" id="2W0UG-4" to="8ntmorv1ep4wgcy/4294fc5d">
  2. <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
  3. <jid>test1@8ntmorv1ep4wgcy/Smack#android</jid>
  4. </bind>
  5. </iq>

这时候的type为result

返回的消息已经告知,时间调度到侦听器。

这时候的用户状态为:<presencetype="unavailable"/>

客户端消息:

  1. <iq id="2W0UG-5" type="set">
  2. <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
  3. </iq>

以上客户端请求会话激活。

下面服务端返回会话激活:

  1. <iq id="2W0UG-5" type="set" from="test1@8ntmorv1ep4wgcy/Smack#android">
  2. <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
  3. </iq>

所有登陆都完成了。

(转)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源码学习之六:用户注册

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43413509 用户注册 注册流程: 1.客户端进行握手给服务端发送连接消息: <s ...

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

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

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

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

  8. Flask学习之五 用户登录

    英文博客地址:http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins 中文翻译地址:http:// ...

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

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

随机推荐

  1. 【转】Java类MemoryUsage查看虚拟机的使用情况

    原文地址:https://www.cnblogs.com/xubiao/p/5465473.html Java类MemoryUsage,通过MemoryUsage可以查看Java 虚拟机的内存池的内存 ...

  2. 二级域名解析设置及Apache 子域名配置

    域名管理解析项 如: cy.wanggangg.top 为wanggangg.top域名添加解析 主机记录设为 cy 记录值 为服务器ip地址 打开apache配置文件 新增如下:<Virtua ...

  3. 为什么重写equals还要重写hashcode

    参考回答: HashMap中,如果要比较key是否相等,要同时使用这两个函数!因为自定义的类的hashcode()方法继承于Object类,其hashcode码为默认的内存地址,这样即便有相同含义的两 ...

  4. python学习笔记:数据类型——数字、字符串、元祖、字典

    计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同的数据,需要定义不同的数 ...

  5. axios interceptors 拦截 , 页面跳转, token 验证 Vue+axios实现登陆拦截,axios封装(报错,鉴权,跳转,拦截,提示)

    Vue+axios实现登陆拦截,axios封装(报错,鉴权,跳转,拦截,提示) :https://blog.csdn.net/H1069495874/article/details/80057107 ...

  6. Python-装饰器的进阶 小知识点

    ⼀. 通⽤装饰器的回顾 开闭原则: 对增加功能开放. 对修改代码封闭 装饰器的作⽤: 在不改变原有代码的基础上给⼀个函数增加功能 通⽤装饰器的写法: def wrapper(fn): def inne ...

  7. Excel_PoweQuery——条件计数、条件求和

    岁月不居,时节如流. 时光荏苒,岁月如梭. 前面两段充分体现了博主深厚的文学素养,别和博主争,博主说啥就是啥. 其实,对于大量数据的处理,这几年微软Office做的不单单是2007的时候把Excel的 ...

  8. mac 卸载编辑器卸不干净

    Configuration ~/Library/Preferences/ Caches ~/Library/Caches/ Plugins ~/Library/Application Support/ ...

  9. 2018年分享的Spring Cloud 2.x系列文章

    还有几个小时2018年就要过去了,盘点一下小编从做做公众号以来发送了273篇文章,其中包含原创文章90篇,虽然原创的有点少,但是2019年小编将一如既往给大家分享跟多的干货,分享工作中的经验,让大家在 ...

  10. 与JS报错的那段时光

    1.Uncaught SyntaxError: Unexpected end of input js报错: 翻译:语法错误:输入意外终止 原因:页面代码写的不规范  ╮(╯▽╰)╭ 其中的某条语句,没 ...