开发openfire 消息拦截器插件PacketInterceptor

时间:2023-03-09 16:42:21
开发openfire 消息拦截器插件PacketInterceptor

开发消息拦截器的步骤跟开发简单插件步骤一样,要开发消息拦截器插件,首先继承PacketInterceptor包拦截类,然后在initializelPlugin()方法中注册拦截器,就可以实现interceptPackage()方法中拦截包(即此方法中的packet参数)了。并且,可以通过入参incoming来判断是服务器发送的包还是接受的包(注:true为服务器接收的包;false为发出的包)。processed参数用处暂不明,猜想是对请求做了什么处理的标识,但不影响我们对包进行拦截和处理。

这个扩展方式与前一种相比的好处在于,这种方式不仅没有修改原注册流程的代码,而且最大程度的使用了原注册流程。这样可以避免一些不必要的风险。

  1. package com.bis.plugin.messageplugin;
  2. import java.io.File;
  3. import org.jivesoftware.openfire.container.Plugin;
  4. import org.jivesoftware.openfire.container.PluginManager;
  5. import org.jivesoftware.openfire.interceptor.InterceptorManager;
  6. import org.jivesoftware.openfire.interceptor.PacketInterceptor;
  7. import org.jivesoftware.openfire.interceptor.PacketRejectedException;
  8. import org.jivesoftware.openfire.session.Session;
  9. import org.xmpp.packet.Packet;
  10. public class MessagePlugIn implements Plugin,PacketInterceptor {
  11. private static PluginManager pluginManager;
  12. private InterceptorManager interceptoerManager;
  13. public MessagePlugIn() {
  14. interceptoerManager = InterceptorManager.getInstance();
  15. }
  16. @Override
  17. public void initializePlugin(PluginManager manager, File pluginDirectory) {
    interceptoerManager = InterceptorManager.getInstance();
  18. pluginManager = manager;
  19. interceptoerManager.addInterceptor(this);
  20. System.out.println("加载插件成功!");
  21. }
  22. @Override
  23. public void destroyPlugin() {
  24. interceptoerManager.removeInterceptor(this);
  25. System.out.println("销毁插件成功!");
  26. }
  27. @Override
  28. public void interceptPacket(Packet packet, Session session,
  29. boolean incoming, boolean processed) throws PacketRejectedException {
  30. System.out.println("接收到的消息内容:"+packet.toXML());
  31. }
  32. }

1、继承Plugin接口,就是在系统启动的时候会执行initializePlugin()方法,表示这是一个插件类

2、继承PacketInterceptor接口,表示这个类是一个拦截Message的消息类,当拦截的时候,会执行interceptPacket方法

关于openfire是如何管理消息拦截器的?

我们可以看看MessageRouter类的route(Message packet)方法

  1. public void route(Message packet) {
  2. if (packet == null) {
  3. throw new NullPointerException();
  4. }
  5. ClientSession session = sessionManager.getSession(packet.getFrom());
  6. try {
  7. // Invoke the interceptors before we process the read packet
  8. //系统的拦截器就是在这里调用的,遍历动态添加的所有拦截器
  9. InterceptorManager.getInstance().invokeInterceptors(packet, session, true, false);
  10. if (session == null || session.getStatus() == Session.STATUS_AUTHENTICATED) {
  11. JID recipientJID = packet.getTo();
  12. // Check if the message was sent to the server hostname
  13. if (recipientJID != null && recipientJID.getNode() == null && recipientJID.getResource() == null &&
  14. serverName.equals(recipientJID.getDomain())) {
  15. if (packet.getElement().element("addresses") != null) {
  16. // Message includes multicast processing instructions. Ask the multicastRouter
  17. // to route this packet
  18. multicastRouter.route(packet);
  19. }
  20. else {
  21. // Message was sent to the server hostname so forward it to a configurable
  22. // set of JID's (probably admin users)
  23. sendMessageToAdmins(packet);
  24. }
  25. return;
  26. }
  27. try {
  28. // Deliver stanza to requested route
  29. routingTable.routePacket(recipientJID, packet, false);
  30. }
  31. catch (Exception e) {
  32. log.error("Failed to route packet: " + packet.toXML(), e);
  33. routingFailed(recipientJID, packet);
  34. }
  35. }
  36. else {
  37. packet.setTo(session.getAddress());
  38. packet.setFrom((JID)null);
  39. packet.setError(PacketError.Condition.not_authorized);
  40. session.process(packet);
  41. }
  42. // Invoke the interceptors after we have processed the read packet
  43. //系统的拦截器就是在这里调用的,遍历动态添加的所有拦截器
  44. InterceptorManager.getInstance().invokeInterceptors(packet, session, true, true);
  45. } catch (PacketRejectedException e) {
  46. // An interceptor rejected this packet
  47. if (session != null && e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
  48. // A message for the rejection will be sent to the sender of the rejected packet
  49. Message reply = new Message();
  50. reply.setID(packet.getID());
  51. reply.setTo(session.getAddress());
  52. reply.setFrom(packet.getTo());
  53. reply.setType(packet.getType());
  54. reply.setThread(packet.getThread());
  55. reply.setBody(e.getRejectionMessage());
  56. session.process(reply);
  57. }
  58. }
  59. }
  1. public void route(Message packet) {
  2. if (packet == null) {
  3. throw new NullPointerException();
  4. }
  5. ClientSession session = sessionManager.getSession(packet.getFrom());
  6. try {
  7. // Invoke the interceptors before we process the read packet
  8. //系统的拦截器就是在这里调用的,遍历动态添加的所有拦截器
  9. InterceptorManager.getInstance().invokeInterceptors(packet, session, true, false);
  10. if (session == null || session.getStatus() == Session.STATUS_AUTHENTICATED) {
  11. JID recipientJID = packet.getTo();
  12. // Check if the message was sent to the server hostname
  13. if (recipientJID != null && recipientJID.getNode() == null && recipientJID.getResource() == null &&
  14. serverName.equals(recipientJID.getDomain())) {
  15. if (packet.getElement().element("addresses") != null) {
  16. // Message includes multicast processing instructions. Ask the multicastRouter
  17. // to route this packet
  18. multicastRouter.route(packet);
  19. }
  20. else {
  21. // Message was sent to the server hostname so forward it to a configurable
  22. // set of JID's (probably admin users)
  23. sendMessageToAdmins(packet);
  24. }
  25. return;
  26. }
  27. try {
  28. // Deliver stanza to requested route
  29. routingTable.routePacket(recipientJID, packet, false);
  30. }
  31. catch (Exception e) {
  32. log.error("Failed to route packet: " + packet.toXML(), e);
  33. routingFailed(recipientJID, packet);
  34. }
  35. }
  36. else {
  37. packet.setTo(session.getAddress());
  38. packet.setFrom((JID)null);
  39. packet.setError(PacketError.Condition.not_authorized);
  40. session.process(packet);
  41. }
  42. // Invoke the interceptors after we have processed the read packet
  43. //系统的拦截器就是在这里调用的,遍历动态添加的所有拦截器
  44. InterceptorManager.getInstance().invokeInterceptors(packet, session, true, true);
  45. } catch (PacketRejectedException e) {
  46. // An interceptor rejected this packet
  47. if (session != null && e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
  48. // A message for the rejection will be sent to the sender of the rejected packet
  49. Message reply = new Message();
  50. reply.setID(packet.getID());
  51. reply.setTo(session.getAddress());
  52. reply.setFrom(packet.getTo());
  53. reply.setType(packet.getType());
  54. reply.setThread(packet.getThread());
  55. reply.setBody(e.getRejectionMessage());
  56. session.process(reply);
  57. }
  58. }
  59. }

最后附上xmpp的相关协议:

  1. .openfire注册相关协议
  2. 1./*用户注册,原本的协议中没有province字段,这里为扩展*/
  3. <iq id="g0G4m-1" to="zhanglj" type="set">
  4. <query xmlns="jabber:iq:register">
  5. <username>re3</username>
  6. <email></email>
  7. <name></name>
  8. <password>1</password>
  9. <province>合肥</province>
  10. </query>
  11. </iq>
  12. 2.用户注册成功
  13. <iq type="result" id="g0G4m-1" from="zhanglj" to="re3@zhanglj/Spark 2.6.3"/>
  14. 3.用户注册失败
  15. i. 用户名为空:code='500"
  16. <iq type="error" id="g0G4m-1" from="zhanglj" to="re3@zhanglj/Spark 2.6.3">
  17. <query xmlns="jabber:iq:register">
  18. <username/>
  19. <email/>
  20. <name/>
  21. <password>1</password>
  22. <province>合肥</province>
  23. </query>
  24. <error code="500" type="wait">
  25. <internal-server-error xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
  26. </error>
  27. </iq>
  28. ii.密码为空:code='406"
  29. <iq type="error" id="g0G4m-1" from="zhanglj" to="re3@zhanglj/Spark 2.6.3">
  30. <query xmlns="jabber:iq:register">
  31. <username>r</username>
  32. <email/>
  33. <name/>
  34. <password/>
  35. </query>
  36. <error code="406" type="modify"><not-acceptable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
  37. </error>
  38. </iq>
  39. iii.用户已存在:code='409"
  40. <iq id="g0G4m-1" to="re3@zhanglj/Spark 2.6.3" from="zhanglj" type="error">
  41. <query xmlns="jabber:iq:register">
  42. <username>re5</username>
  43. <email/>
  44. <name/>
  45. <province>合肥</province>
  46. <password>1</password>
  47. </query>
  48. <error code="409" type="CANCEL">
  49. <conflict xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
  50. </error>
  51. </iq>

https://blog.csdn.net/zhonglunshun/article/details/84695804