您的位置:首页 > 运维架构

Openfire4.0.2中以插件形式替换默认的用户登录认证机制

2016-05-14 00:21 441 查看
=======20160627 Begin ========

更正:通过多次尝试,和openfire源码分析,发现openfire是不能以插件形式替换默认登录机制的.会提示找不到自定义的Provider,因为openfire查找Provider会在openfire/lib目录下查找,并不会在openfire/plugins/下查找.所以解决方法是:把写好的Provider打成jar包,放到openfire/lib下,再替换默认的登录机制,即可实现登录机制替换.

替换后,会出现不少问题.具体的问题可以根据异常方法栈找到解决方法,一般是因为:换了登录机制后,必须要重写许多方法,比如createUser等,否则,当你在控制台上新建用户时,就会出现异常.

=======20160627 End========

前言:

我的openfire使用的是内置的数据库,如果不是内置的数据库,解决方案也类似.

亲,如果你还不会配Openfire,或是还不会写openfire的 插件,或是还不会用Ant编译插件,可以参看我转载的这篇文章:http://blog.csdn.net/lc0817/article/details/51379432

先说说我是如何替换默认登录机制的(如果你不关心过程,只关心结果,可以跳过前言部分)

1.通过百度,发现客户端认证与UserProvider,AuthProvider这个两接口有关.(这里只分析UserProvider,authProvider类似)

2.利用Eclipse,找到UserProvider接口的所有实现类,有CrowdUserProvider,DefaultUserProvider,HybridUserProvider等等.

3.聪明的你,看到DefaultUserProvider就应该和我有一样的想法了.

4.通过outline看到DefaultUserProvider中比较可疑的的方法有loadUser,于是我就在此处syso了一下.

5.使用openfire官网提供的Spark作为客户端来连接localhost:5222.

6.发现loadUser中的syso有被打印出来.

7.在loadUser中,打印stackTrace,打印stackTrace的方法:new Throwable().getStackTrace(). 下面是打印的内容:

org.jivesoftware.openfire.user.DefaultUserProvider.loadUser
org.jivesoftware.openfire.user.UserManager.getUser
org.jivesoftware.openfire.user.UserManager.isRegisteredUser
org.jivesoftware.openfire.auth.AuthToken.isAnonymous
org.jivesoftware.openfire.handler.IQBindHandler.handleIQ
org.jivesoftware.openfire.handler.IQHandler.process
org.jivesoftware.openfire.IQRouter.handle
org.jivesoftware.openfire.IQRouter.route
org.jivesoftware.openfire.spi.PacketRouterImpl.route
org.jivesoftware.openfire.net.StanzaHandler.processIQ
org.jivesoftware.openfire.net.ClientStanzaHandler.processIQ
org.jivesoftware.openfire.net.StanzaHandler.process
org.jivesoftware.openfire.net.StanzaHandler.process
org.jivesoftware.openfire.nio.ConnectionHandler.messageReceived
org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.messageReceived
org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived
org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1200
org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived
org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived
org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived
org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1200
org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived
org.apache.mina.filter.codec.ProtocolCodecFilter$ProtocolDecoderOutputImpl.flush
org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived
org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived
org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1200
org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived
org.apache.mina.core.filterchain.IoFilterEvent.fire
org.apache.mina.core.session.IoEvent.run
org.apache.mina.filter.executor.OrderedThreadPoolExecutor$Worker.runTask
org.apache.mina.filter.executor.OrderedThreadPoolExecutor$Worker.runTasks
org.apache.mina.filter.executor.OrderedThreadPoolExecutor$Worker.run
java.lang.Thread.run


8.根据方法栈中的信息,可以知道客户端登录时所走的流程了.

9.进入UserManager,找到UserProvider初始化的方法:initProvider()

private void initProvider() {
// Convert XML based provider setup to Database based
JiveGlobals.migrateProperty("provider.user.className");

String className = JiveGlobals.getProperty("provider.user.className",
"org.jivesoftware.openfire.user.DefaultUserProvider");
// Check if we need to reset the provider class
if (provider == null || !className.equals(provider.getClass().getName())) {
try {
Class c = ClassUtils.forName(className);
provider = (UserProvider) c.newInstance();
}
catch (Exception e) {
Log.error("Error loading user provider: " + className, e);
provider = new DefaultUserProvider();
}
}
}
10.可以看到,这里是通过JiveGlobals来获取的,我们再进一步去看它的property是在哪里初始化的.

11.Eclipse中按Ctrl+H全局搜索"provider.user.className",但是可惜,找不到合适的东东.所以我怀疑,它不是存在XML里的.

12.进入JiveGlobals,通过观察它所有的fields,加上许多验证,最终确定是properties字段.

13.找到初始化properties的方法JiveProperties.getInstance(),最后一步一步深入进去,找到真相了!

14.在JiveProperties.loadProperties()中,它加载了内嵌数据库中的内容,数据库的脚本在:\openfire_src\target\openfire\embedded-db\openfire.script.

15.修改其中的provider.user.className所对应的值.

16.Ant一下整个工程,大功告成.

===========================华====丽====的====分====割====线==========================

现在开始具体做法:

1.创建一个插件:


2.Ant这个插件一下.

3.修改openfire_src\target\openfire\embedded-db\openfire.script中的provider.user.className为对应的插件类名全路径.如果没有该文件,需要先Ant一下整个工程.并且登录localhost:9090进行向导配置.

4.Ant一下整个工程

5.启动工程,用Spark登录,你会发现,你的插件已经被初始化,并且替代了DefaultUserProvider.

鉴权插件的做法也类似,只要有一个实现了AuthProvider的插件,并修改"provider.auth.className"即可.鉴权流程的源码阅读方式与UserProvider类似.

如有不明白的地方,欢迎留言.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: