IM即时聊天系统-Openfire爬坑之路三 插件1

2020-04-24  本文已影响0人  渝潼不肖生

插件结构

myplugin /
 |-pom.xml <-Maven项目的插件描述/配置文件(允许您定义Maven使用的POM(项目对象模型)。
 |-plugin.xml <-插件定义文件
 |-readme.html <-插件的可选自述文件,它将显示给最终用户
 |-changelog.html <-插件的可选changelog文件,它将显示给最终用户
 |-logo_small.gif <-与插件关联的可选小(16x16)图标(也可以是.png文件)
 |-logo_large.gif <-与插件关联的可选大(32x32)图标(也可以是.png文件)
 |-src   
    |-classes / <-插件所需的资源(即属性文件)
    |-database/ <-插件所需的可选数据库架构文件
    |-i18n / <-可选的i18n文件,以允许插件国际化。
    |-lib / <-插件需要的库(JAR文件)
    |-java / <-这是包含插件应用程序(.java文件)源的目录,位于软件包中
    |-web <-管理控制台集成的资源(如果有)
        |-WEB-INF /
            |-web.xml <-包含编译的JSP条目的生成的web.xml
            |-web-custom.xml <-自定义servlet的可选用户定义的web.xml
        |-images/

plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
    <!-- 插件主类 -->
    <class>org.example.ExamplePlugin</class>

    <!--插件信息-->
    <name>Example Plugin</name>
    <description>This is an example plugin.</description>
    <author>阿伦</author>
    <version>1.0</version>
    <date>07/01/2006</date>
    <url>http://www.baidu.com</url>
    <minServerVersion>3.0.0</minServerVersion>
    <licenseType>gpl</licenseType>

    <!-- 管理控制台条目 -->
    <adminconsole>
        <!-- 控制台内容 -->
    </adminconsole>
</plugin>
INSERT INTO ofVersion (name, version) VALUES ('foo', 0);
UPDATE ofVersion set version=1 where name='foo';

“commercial”:该插件是根据商业许可协议发布的。
“gpl”:该插件是根据GNU公共许可证(GPL)发布的。
“apache”:该插件根据Apache许可发布。
“internal”:该插件仅供组织内部使用,不会重新分发。
“other”:该插件是根据许可协议发行的,该许可协议不属于其他类别之一。许可协议应该是插件自述文件中的详细信息。
如果未设置许可证类型,则假定为其他。

插件中可以存在几个其他文件,以向最终用户提供其他信息(所有信息都放置在主插件目录中):

实现 Plugin接口

插件实现Openfire APIPlugin 接口,并且必须具有默认(无参数)构造函数。Plugin接口具有用于初始化和销毁​​插件的方法。

package org.example;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import java.io.File;
/**
 *实例
 */
public class ExamplePlugin implements Plugin {
    //初始插件回调
    public void initializePlugin(PluginManager manager, File pluginDirectory) {
        // 这里写你的代码
    }
  //销毁插件回调
    public void destroyPlugin() {
        // 这里写你的代码
    }
}

修改管理控制台

插件可以将标签,部分和页面添加到管理控制台。步骤:

plugin.xml的<adminconsole />部分定义了管理控制台框架中的其他选项卡,部分和条目。一个示例 plugin.xml文件可能如下所示:
plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
    <!-- Main plugin class -->
    <class>org.example.ExamplePlugin</class>
    <!-- Admin console entries -->
    <adminconsole>
        <tab id="mytab" name="Example" url="my-plugin-admin.jsp" description="Click to manage...">
            <sidebar id="mysidebar" name="My Plugin">
               <item id="my-plugin" name="My Plugin Admin"
                   url="my-plugin-admin.jsp"
                   description="Click to administer settings for my plugin"
                   order="4" />
               <item id="my-plugin" name="My Plugin Overview"
                   url="my-plugin-overview.jsp"
                   description="Click to have an Overview of Plugin usage"
                   order="2" />
            </sidebar>
        </tab>
    </adminconsole>
</plugin>

在此示例中,我们定义了一个新选项卡“ Example”,一个侧栏部分“ My Plugin”和两个页面:“ My Plugin Admin”和“ My Plugin Overview”。我们已经分别将my-plugin-admin.jsp和my-plugin-overview.jsp注册 为页面。
默认情况下,选项卡,侧边栏和页面将按照定义顺序显示。但是,您可以通过向每个元素添加“ order”属性来定义显式排序。它的数值定义顺序。如果未指定任何顺序,则默认值为0。在上面的示例中,使用此构造对项目​​进行排序。在管理控制台中,“My Plugin Overview”页面将在“My Plugin Admin”页面之前显示,因为其“order”值较低。如果两个项目都未定义'order'属性,则两个页面的显示都将被反转(因为它曾经用来对以XML定义页面的顺序进行排序)。
您可以使用自己的<adminconsole>定义中的现有id属性值来覆盖现有的tabs, sections和items 。

管理控制台最佳做法

通过插件更改Openfire管理控制台时,需要考虑几种最佳做法。一般主题是插件应无缝集成:

编写管理控制台页面

Openfire使用Sitemesh 框架在管理控制台中装饰页面。如下图所示,将全局定义的装饰器应用于每个页面以呈现最终输出:

Sitemesh

创建适用于Sitemesh的页面很容易。只需创建有效的HTML页面,然后使用元标记将指令发送到Sitemesh。呈现输出时,Sitemesh将使用您提供的说明来呈现装饰器以及HTML页面正文中的任何内容。可以使用以下元标记:

   <html>
       <head>
           <title>My Plugin Page</title>
           <meta name="pageID" content="myPluginPage"/>
       </head>
       <body>
            Body here!
       </body>
   </html>

在插件中使用i18n

可以将您的插件翻译成多种语言(i18n)。为此,请使用以下过程:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
 ...
<fmt:message key="some.key.name" />
org.jivesoftware.util.LocaleUtils.getLocalizedString("some.key.name", "[plugin_name]");

使用$ {var}格式将plugin.xml文件中的字符串国际化:

<sidebar id="gateways" name="${plugin.sidebar.name}" description="${plugin.sidebar.description}">
<description>${plugin.description}</description>

使用Openfire构建脚本
Openfire构建脚本将帮助您构建和开发插件。它以以下格式查找插件开发目录:
插件结构

myplugin/
 |- plugin.xml      <- Plugin definition file
 |- readme.html     <- Optional readme file for plugin
 |- changelog.html  <- Optional changelog file for plugin
 |- logo_small.gif  <- Optional small (16x16) icon associated with the plugin (can also be a .png file)
 |- logo_large.gif  <- Optional large (32x32) icon associated with the plugin (can also be a .png file)
 |- classes/        <- Resources your plugin needs (i.e., a properties file)
 |- lib/            <- Libraries your plugin needs
 |- src/
     |- database    <- Optional database scripts for your plugin
     |- java        <- Java source code for your plugin
     |   |- com
     |       |- mycompany
     |           |- *.java
     |- web
         |- *.jsp      <- JSPs your plugin uses for the admin console
         |- images/    <- Any images your JSP pages need (optional)
         |- WEB-INF
             |- web.xml    <- Optional file where custom servlets can be registered

构建脚本将编译源文件和JSP,并创建有效的插件结构和JAR文件。将您的插件目录放在 源发行版的src / plugins目录中,然后使用ant插件来构建您的插件。

您的插件在编译过程中需要的所有JAR文件都应放在lib目录中。在构建过程中,还将这些JAR文件复制到插件的生成的lib目录中。

如果创建src / web / WEB-INF / web.xml文件,则在插件启动时将初始化在此注册的所有servlet。从web.xml文件中仅接受servlet注册和servlet映射。注意:此功能是通过将您的自定义web.xml文件合并到JSP编译过程生成的web.xml文件中来实现的。
***********=============现在推荐用maven构建,下一章介绍===========************

实施您的插件

插件具有对Openfire API的完全访问权限。这为插件可以完成的工作提供了极大的灵活性。但是,有几个最常见的集成点:

  1. 将插件注册为Component。组件接收所有发往特定子域的数据包。例如, test_component.example.com。因此,发送到 joe_component.example.com 的数据包将被传递到该组件。请注意,定义为组件的子域与子域的DNS条目无关。套接字级别的所有XMPP路由都使用主服务器域(在上面的示例中为example.com)完成;子域仅用于XMPP服务器中的路由。

  2. 将插件注册为IQHandler。IQ处理程序以特定的元素名称和名称空间响应IQ数据包。以下代码段演示了如何注册IQHandler:

  IQHandler myHandler = new MyIQHander();
  IQRouter iqRouter = XMPPServer.getInstance().getIQRouter();
  iqRouter.addHandler(myHandler);

  1. 将插件注册为 PacketInterceptor以接收通过系统发送的所有数据包,并有选择地拒绝它们。例如,拦截器可以拒绝所有包含敏感词的邮件或将其标记为由管理员查看。

  2. 您可以使用JiveGlobals.getProperty(String)和JiveGlobals.setProperty(String,String)方法将持久性插件设置存储为Openfire属性。通过实现org.jivesoftware.util.PropertyEventListener方法,使插件成为属性侦听器,以侦听对其属性的更改 。您可以使用PropertyEventDispatcher.addListener(PropertyEventListener)方法将插件注册为侦听器。确保在插件的destroyPlugin()方法中将插件注册为侦听器。

Openfire管理员标签

Openfire提供了可以使用的有用的JSP标签。要在JSP页面上启用它们,只需在JSP页面

<%@ taglib uri="admin" prefix="admin" %> 

顶部添加标签,包括:

<admin:ASN1DER value="${ASN.1 DER certificate as a byte[]}"/>
<!-- (自Openfire 4.0.0起)将在HTML表中显示ASN.1 DER编码的证书。-->
<admin:FlashMessage/>
<!--(自Openfire 4.5.0起)将在呈现的页面上最多显示三个经过适当装饰的会话属性。
这些会话属性的密钥是由定义 FlashMessageTag.SUCCESS_MESSAGE_KEY,
WARNING_MESSAGE_KEY和 ERROR_MESSAGE_KEY。这允许在页面之间
导航时向用户显示消息。-->

CSRF保护

管理员页面容易受到CSRF攻击。Openfire提供了一些工具来帮助插件作者在其管理页面上防御这些攻击。启用CSRF保护:

  1. 将plugin.xml设置minServerVersion为4.5.0或更高版本,因为这是添加支持时的状态。
  2. 将plugin.xml csrfProtectionEnabled设置true为启用插件的CSRF保护。这将;
    • 防范CSRF攻击,除了 GET请求,所有对管理页面的请求
    • 使用键“ csrf”设置servlet请求属性
  3. 确保GET请求不会修改任何设置或更改任何数据,因为未为GET请求启用此保护
  4. 确保在管理页面中提交的任何表单都有一个名为csrf的字段,该字段的值由请求属性“ csrf”定义-例如:
<input name="csrf" value="<c:out value="${csrf}"/>" type="hidden">

如果检测到CSRF攻击,将使用FlashMessageTag.ERROR_MESSAGE_KEY设置了session属性以指示问题的状态(使用简单的HTTP GET请求)重新加载管理页面-因此建议<admin:FlashMessage/>在JSP页面的顶部包含。
注意 :使用<c:out>标签或等效标签确保所有输出正确转义仍然很重要 。

插件常见问题

我可以将插件部署为目录而不是JAR吗?
不,所有插件都必须部署为JAR或WAR文件。当插件不存在JAR或WAR时,Openfire会假定该文件已被删除,并且用户希望销毁该插件,因此它也会删除该目录。

上一篇下一篇

猜你喜欢

热点阅读