即时聊天IM之二 openfire 整合现有系统用户

合肥程序员群:49313181。    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入)
Q  Q:408365330     E-Mail:egojit@qq.com

 综述:

每天利用中午时间更新下这个知识点的的博客如果感兴趣的觉得更新慢了也别介意(其它时间还是以工作为主,学习工作两不误,哈哈……)。上一篇我纯理论上简单讲解了一下XMPP协议,然而现在用的比较多的XMPP协议服务器当然是openfire最为流行(我感觉)。至于如何搭建oprenfire 二次开发环境并且将代码跑起来,这一篇不介绍了,后面下一篇介绍,也许会有点顺序乱的感觉,但是主要还是我最近两天再搞IM整合现有系统用户。所以这一遍是记录篇也是发出来和大家一起分享心得(毕竟网上很多博客是没有经过验证的理论篇),我这里都是经过实际环境并且通过测试的,否则我不会记录。在这里我们需要两份源代码,因为在配置中我们会进行源码调试,一方面我们要读openfire源码,另一方面我们要一个客户端登录XMPP服务器聊天验证,首先上着两份源码在eclipse中的结构(后面会记录如何搭建源码环境并且将源码跑起来)

图1

首先Openfire 的源码使用的是最新的3.10.2版本,客户端Spark 是pc客户端,使用的是最新的2.7.2版本,如上图所示。

首先描述一下业务场景,公司有一个现有的OA系统,是.NET(C#语言)平台下开发的,使用SqlServer数据库。让后给OA加上即时聊天功能,本来是打算维护两份用户数据,后来了解到现有OA的用户是密码是MD5加密,而openfire默认是Blowfish加密,这个时候如果是新建用户还好,但是以前在使用的OA系统中MD5加密的用户怎么办??如果直接导入到IM用户表中肯定是无法使用的,这个时候就需要整合现有用户表,openfire中的用户表废弃,只使用现有系统中的用户表,OA系统和openfire都是通过OA系统用户表登录,所以需要整合。然后就免不了分析openfire源码,才有了下面的文字,根据openfire源码让你知其然知其所以然。否则只知道这样配置,而不知道为什么这样配置,那就不好了,凡事弄明明白白(程序猿精神)。

openfire整合现有系统用户

首先明确我的现有系统是一个SqlServer数据库,IM也是sqlserver(当然混合数据库也是可以的,已经这样做过IM是mysql,就有系统是SqlServer)。

一.配置provider.auth.className

 

private static void initProvider() {// Convert XML based provider setup to Database basedJiveGlobals.migrateProperty("provider.auth.className");String className = JiveGlobals.getProperty("provider.auth.className","org.jivesoftware.openfire.auth.DefaultAuthProvider");// Check if we need to reset the auth provider class if (authProvider == null || !className.equals(authProvider.getClass().getName())) {try {Class c = ClassUtils.forName(className);authProvider = (AuthProvider)c.newInstance();}catch (Exception e) {Log.error("Error loading auth provider: " + className, e);authProvider = new DefaultAuthProvider();}}}

由openfire源码中AuthFactory类我们知道它的静态函数中调用了这个initProvider()这个静态函数初始化了一些配置,然后通过这个配置构造了一个AuthProvider。这个配置的键为provider.auth.className,默认使用的是org.jivesoftware.openfire.auth.DefaultAuthProvider类,如果我们配置provider.auth.className那么就使用配置的类,然后我们就可以在

openfire源码中找DefaultAuthProvider类 继承自JDBCAuthProvider,继承自AuthProvider类完全符合要求,在数据库中修改ofProperty表相应的值,如下图:

图2

这样用户验证就是通过org.jivesoftware.openfire.auth.JDBCAuthProvider来进行行验证了。我们继续跟踪openfire的java源码,进入JDBCAuthProvider类,它的构造函数代码如下:

图3

由图3很容易知道,我们要配置各种参数如下:

驱动: jdbcProvider.driver

连接字符串:jdbcProvider.connectionString

查询密码的SQL语句:jdbcAuthProvider.passwordSQL

密码的加密类型:jdbcAuthProvider.passwordType

设置密码的SQL语句:jdbcAuthProvider.setPasswordSQL

是否允许修改密码(由后面的源码知道true或者false):allowUpdate 

那么我们现在来一个一个跟踪源码讲解整合用户。

1.配置驱动jdbcProvider.driver  这里是SQL server数据库所以用 net.sourceforge.jtds.jdbc.Driver。

2.配置连接字符串jdbcProvider.connectionString  为: jdbc:jtds:sqlserver://192.168.11.21:1433/OA_frame;appName=jive;user=sa;password=mm  替换成你自己的

3.配置查询密码字符串jdbcAuthProvider.passwordSQL 为: select UserPwd from BT_User where UserName=?  这里的 UserName是用户登录名称,UserPwd就是密码字段,BT_User就是用户表。为什么是这样请看下面源代码就懂了:

 

图5 

 4.配置密码加密类型jdbcAuthProvider.passwordType   为md5  ,但是一定要注意要小些字符串"md5"如果问为什么,那是因为openfire源码中不认识"MD5"这种大写。这个支持哪些加密方式呢??很容易有下面的枚举知道:plain不加密,md5,sha1,sha256,sha512这些加密方式

 1  public enum PasswordType {
 2 
 3         /**
 4          * The password is stored as plain text.
 5          */
 6         plain,
 7 
 8         /**
 9          * The password is stored as a hex-encoded MD5 hash.
10          */
11         md5,
12 
13         /**
14          * The password is stored as a hex-encoded SHA-1 hash.
15          */
16         sha1,
17         
18         /**
19          * The password is stored as a hex-encoded SHA-256 hash.
20          */
21         sha256,
22               
23         /**
24           * The password is stored as a hex-encoded SHA-512 hash.
25           */
26         sha512;
27    }

5. 设置 修改密码SQL脚本jdbcAuthProvider.setPasswordSQL  根据自己的需要设置修改密码脚本,根据源码可以知道它也是把用户登录名作为条件查询修改的,也就是修改制定登录名用 户的密码。

6. 配置是否允许修改密码allowUpdate    如果配置了jdbcAuthProvider.setPasswordSQL 就插入true吧。否则jdbcAuthProvider.setPasswordSQL 配置的就没有用了,看代码为什么

图6

通过图6制定为什么了吧??:)

 

二.配置provider.user.className

 我们配置provider.user.className为 org.jivesoftware.openfire.user.JDBCUserProvider 请看上面图2。这个配置好了,那么我们就要配置相关属性了。看下图代码:

 图7

 很容易看出在这里我们要配置哪些属性:

1.jdbcProvider.driver(上面已经配置)

2.jdbcProvider.connectionString(上面已经配置)

3.jdbcUserProvider.loadUserSQL

4.jdbcUserProvider.userCountSQL

5.jdbcUserProvider.allUsersSQL

6.jdbcUserProvider.searchSQL

7.jdbcUserProvider.usernameField

8.jdbcUserProvider.nameField

9.jdbcUserProvider.emailField

1.配置加载用户信息SQL脚本jdbcUserProvider.loadUserSQL  是根据登录名查询用户信息的字符串 select RealName,Email from BT_User where UserName=? 我们再看看源码:

 图8

 由上面图8知道,我们查询只需要查询出用户名(不是登录名),邮箱就行了,其它的查询出来也没什么用,而且字段顺序要正确哦(看源码知道用户第一次被加载后就放入了缓存)。

2.配置查询用户数量脚本jdbcUserProvider.userCountSQL 为:select count(*) from  BT_User   这个就没什么好说明的了

3.配置用户登录名字段 jdbcUserProvider.usernameField  我们这里就是UserName了

4.配置用户名jdbcUserProvider.nameField 为:RealName  这里是昵称或者是真实姓名,这个就看你具体业务了因为这个是要展示给用户看到的

5.配置邮箱字段jdbcUserProvider.emailField 为:Email 就是用户邮箱没什么可说的

结束:

 上面围绕配置JDBCAuthProvider和JDBCUserProvider 到这里就完成了,重启openfire然后这个时候重新登录用户发现现在所用的用户就是旧有系统中的用户了,用户整合完成(至少也只是用户数据整合完成)。更多的配置:如果你系统中有用户部门什么的,还有如果你希望openfire支持整合后用户有更多操作那么还需要配置其它东西,我就不一个个说明,但是遵循这种源码跟踪思路足够应付各种配置,已经配置中出现的问题。

综合配置点:

一):provider.auth.className

  驱动: jdbcProvider.driver

  连接字符串:jdbcProvider.connectionString

  查询密码的SQL语句:jdbcAuthProvider.passwordSQL

  密码的加密类型:jdbcAuthProvider.passwordType

  设置密码的SQL语句:jdbcAuthProvider.setPasswordSQL

  是否允许修改密码(由后面的源码知道true或者false):allowUpdate 

二):provider.auth.className

  jdbcProvider.driver(上面已经配置)

  jdbcProvider.connectionString(上面已经配置)

  jdbcUserProvider.loadUserSQL

  jdbcUserProvider.userCountSQL

  jdbcUserProvider.allUsersSQL

  jdbcUserProvider.searchSQL

  jdbcUserProvider.usernameField

  jdbcUserProvider.nameField

  jdbcUserProvider.emailField

后记:

有兴趣或者有问题的可以加上面的QQ群讨论有什么问题咨询的欢迎打扰。商业合作当然更欢迎

 

 

转载于:https://www.cnblogs.com/egojit/p/4900726.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/375450.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cannot convert ‘_IO_FILE*’ to ‘const char*

错误代码 #ifdef NDEBUG#define DBUG_PRINT(fmt, ...) #else#define DBUG_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__) #endifBUG_PRINT(stderr, "decode %s does not support device type cuda.\n", dec->name);修改 BUG_PRINT("decode %s does not supp…

找出数组中前K大的值

将数组划分为两部分&#xff0c;前K项为前K大值的集合&#xff0c;无需有序。 while(true) {int flag nums[k];while(i < k && nums[i] > flag) {i;}while(j>k && nums[j] < flag) {j--;}if (i j || nums[i] nums[j]) {break;}int tmp nums[i]…

C#在ASP.NET4.5框架下的首次网页应用

运行效果预览: 先看实践应用要求: 1&#xff0e;编写一个函数&#xff0c;用于计算1&#xff01;2&#xff01;3&#xff01;4&#xff01;5&#xff01;&#xff0c;在控制台或页面输出运行结果。 2&#xff0e;在控制台或页面输出九九乘法表。 3&#xff0e;输入10个以内的整…

javascript的变态位运算

javascript的变态位运算 var a "10" | 0; alert(a); alert (typeof a);结果为10,number。 这就是说这条语句可以将字符串转化为number。 如果&#xff1a;var a "sss" | 0;alert(a);结果为0.parseInt("sss")的话&#xff0c;会返回NaN。这个太…

CUDA: OpenCV requires enabled ‘cudev‘ module from ‘opencv_contrib

wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.X.X.zip unzip opencv_contrib.zip cmake -D OPENCV_EXTRA_MODULES_PATH~/opencv_contrib-4.X.X/modules参考

Android-Universal-Image-Loader三大组件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration详解...

转 一、介绍 Android-Universal-Image-Loader是 一个开源的UI组件程序&#xff0c;该项目的目的是提供一个可重复使用的仪器为异步图像加载&#xff0c;缓存和显示。所以&#xff0c;如果你的程序里需要这个功能的话&#xff0c;那么不妨试试它。 因为已经封装好了一些类和方法…

营销类文章 SEO

如何有效的推广网站 适合没钱的中小站长 唐世军 a5总经理 博客 门户网站广告报价—以新浪为例 贵的一天30多万 碧蓝天营销学院 网络营销&#xff0c;你真的了解吗&#xff1f; SEO工具mozBar介绍、友情链接新参考mozRank 谈谈网络推广团队每天工作流程、工作标准、考核 请问安卓…

显示 grep 结果的指定行

用grep查找特定关键字&#xff0c;结果很多&#xff0c;但是有用的在中间的某几行&#xff0c;即grep得到结果之后再次过滤出指定几行。 首先查找指定行 grep -a "X" filename | grep -an "X"记下指定行&#xff0c;然后用awk打印指定行 grep -a "…

Java小知识

内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。(1)、内部类仍然是一个独立的类&#xff0c;在编译之后内部类会被编译成独立的.class文件&#xff0c;但是前面冠以外部类的类名和$符号。(2)、内部类不能用普通的方式访问。成员变量成员变量静态成员变量。List遍…

C++ 设置线程名字

使用 std::thread #include <thread> #include <pthread.h>std::thread t(funs, args); pthread_setname_np(t.native_handle(), threadName);通过 pthread_create 创建 #define _GNU_SOURCE #include <pthread.h>pthread_t tid; pthread_create(&ti…

java学习_File属性处理

// TODO Auto-generated method stub File filenew File("newhello.txt"); //文件是否存在 System.out.println("文件是否存在&#xff1a;"file.exists()); //读取文件名称 System.out.println("读取文件名&#xff1a;"file.getName()); //读取…

pytest 基础讲解

文章目录 一、前置说明二、操作步骤1. 安装 pytest2. python 编写测试用例3. 在 pycharm 中使用 pytest 运行测试用例1)执行单条用例:点击用例前面的三角形执行,或在用例内部点击右键2)执行多条用例:在测试用例的外部区域,点击右键,批量执行所有用例4. 命令行中使用 pyt…

Myeclipse8.6中安装SVN插件

方法一&#xff1a; 1.打开HELP->MyEclipse Configuration Center&#xff0c;切换到SoftWare标签页。   2.点击Add Site 打开对话框&#xff0c;在对话框Name输入Svn&#xff0c;URL中输入&#xff1a;http://subclipse.tigris.org/update_1.6.x   3.在左边栏中找到Per…

初识EL

一、EL函数库介绍 由于在JSP页面中显示数据时&#xff0c;经常需要对显示的字符串进行处理&#xff0c;SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用。  这些EL函数在JSTL开发包中进行描述&#xff0c;因此在JSP页面中使用SUN公司的EL函数库&#xff0c;需要导入…

ffmpeg 合并 flv 文件

// 转ts char cmd[1024] {\0}; sprintf(cmd, "ffmpeg -i %s -loglevel quiet -c copy -bsf:v h264_mp4toannexb -f mpegts %s", lastFlvFile.c_str(), lastTsFile.c_str()); system(cmd);// 合并ts char cmd[1024] {\0}; sprintf(cmd, "ffmpeg -i concat:\&qu…

怎么样的理解才是完全理解SQL(二)

如果我们从集合论&#xff08;关系代数&#xff09;的角度来看&#xff0c;一张数据库的表就是一组数据元的关系&#xff0c;而每个 SQL 语句会改变一种或数种关系&#xff0c;从而产生出新的数据元的关系&#xff08;即产生新的表&#xff09;。我们学到了什么&#xff1f;思考…

Scala学习笔记-环境搭建以及简单语法

关于环境的搭建&#xff0c;去官网下载JDK8和Scala的IDE就可以了&#xff0c;Scala的IDE是基于Eclipse的。 下面直接上代码&#xff1a; 这是项目目录&#xff1a; A是scala写的&#xff1a; package first import scala.collection.mutable.ListBufferobject A {def main(args…

UVa 12169 (枚举+扩展欧几里得) Disgruntled Judge

题意&#xff1a; 给出四个数T, a, b, x1,按公式生成序列 xi (a*xi-1 b) % 10001 (2 ≤ i ≤ 2T) 给出T和奇数项xi&#xff0c;输出偶数项xi 分析&#xff1a; 最简单的办法就是直接枚举a、b&#xff0c;看看与输入是否相符。 1 #include <cstdio>2 3 const int maxn …

使用Beautifulsoup爬取药智网数据

使用Beautifulsoup模块爬取药智网数据 Tips&#xff1a;1.爬取多页时&#xff0c;先用一页的做测试&#xff0c;要不然ip容易被封 2.自己常用的处理数据的方法&#xff1a; regre.compile(正则表达式) datareg.sub(要替换的字符串,data) 代码&#xff08;其实没多少&#xff09…

幂集 返回某集合的所有子集

幂集。编写一种方法&#xff0c;返回某集合的所有子集。集合中不包含重复的元素。 说明&#xff1a;解集不能包含重复的子集。 示例: 输入&#xff1a; nums [1,2,3]输出&#xff1a; [[3],[1],[2],[1,2,3],[1,3],[2,3],[1,2],[] ]来源&#xff1a;力扣&#xff08;LeetCode…