XMPP服务器, BOSH(Http-Binding)和WEB客户端搭建

目标: 搭建一个XMPP服务器, 实现在web page上用javascript与自己XMPP服务器通信, 匿名登录并与任何一个XMPP(Jabber)帐户通信. (Gtalk目前尚有问题)

XMPP服务器可能不是必须的(见下文, 我没有尝试)

环境与配置:

XMPP服务器: ejabberd 文档
HTTP-Binding: 使用ejabberd搭建, 5280端口.
Javascript Client: Strophe 文档

安装Ejabberd

  1. yum  install ejabberd
  2. #apt-get install ejabberd

编辑配置文件: /etc/ejabberd/ejabberd.cfg, 这是个era lang格式配置文件, 行注释符号是%. 请参考ejabberd文档.

下面是默认配置文件里我修改过部分:

%%debug
{loglevel, 5}.
{hosts, ["sagan.me"]}.
{host_config, "sagan.me", [{auth_method, [anonymous,internal]},{anonymous_protocol, sasl_anon}]}.

{listen,
 [
  {5222, ejabberd_c2s, [
                        {certfile, "/path/to/ssl/cert.pem"},
                        %%starttls,
                        starttls_required,
                        {access, c2s},
                        {shaper, c2s_shaper},
                        {max_stanza_size, 65536}
                       ]},
  {5269, ejabberd_s2s_in, [
                           {shaper, s2s_shaper},
                           {max_stanza_size, 131072}
                          ]},
  {{5280, "127.0.0.1"}, ejabberd_http, [
                        {request_handlers, [{["http-bind"], mod_http_bind}]},
                         captcha
                        ]}

 ]}.
{s2s_use_starttls, true}.
{s2s_certfile, "/path/to/ssl/cert.pem"}.
{s2s_default_policy, allow}.
{auth_method, [internal, anonymous]}.

上面配置中, 声明监听127.0.0.1(本地IP地址) 5280端口为http-binding (BOSH)服务地址, 路径是"http-bind", 即服务实际URI是"http://127.0.0.1:5280/http-bind". 然后需要在web服务器配置中用mod_proxy或mod_rewrite将80或443端口上对 "/http-bind" 访问转发到"http://127.0.0.1:5280/http-bind", 因为由于浏览器同源限制, yourdomain.com:80上的web page是无法直接向yourdomain.tld:5280提交ajax请求的. ( 所以在上面配置中把ejabberd http-bind监听的端口设为了127.0.0.1:5280, 即不能从外部直接访问)

添加域名DNS SRV记录

这一步是必须的, 否则搭建的XMPP服务器基本上无法与大多数其它服务器或客户端通信. (插一句: Google Apps Talk基于XMPP平台, 如果不设置域名SRV记录的话, 就只能够用Gtalk登录(无法使用其它XMPP客户端), 而且只能和gmail.com或其它Google Apps域名的帐户通信)

_xmpp-client._tcp.sagan.me. 86400 IN SRV 10 0 5222 sagan.me.
_xmpp-server._tcp.sagan.me. 86400 IN SRV 10 0 5269 sagan.me.

5269和5222是XMPP在ICANN注册的标准端口.

修改WEB服务器配置

我的Lighttpd ModProxy配置:

proxy.server = (
        "/http-bind" => ( (
                "host" => "127.0.0.1",
                "port" => 5280
        ) )
)

应该也可以用web服务器直接转发请求到外部某个公开的Jabber (XMPP)服务器 http-bind地址, 我没有尝试. (基本上找不到公开的提供http-bind的XMPP服务器)

使用Javascript客户端

上面ejabberd配置里开启了匿名登录(ANOYMOUS mechanism), 最终目的就是为了在web page中匿名访问服务并向任何一个XMPP帐户发送消息.

下载Strophe JS库并上传到你的域名目录下(这个库只有一个文件strophe.js), 下面这个测试例子修改自Strophe examples目录下echobot.html

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4.   <title>Strophe.js Echobot Example</title>
  5.   <script type='text/javascript'
  6.           src='http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js'></script>
  7.   <script type='text/javascript'
  8.           src='../strophe.js'></script>
  9.   <script type='text/javascript'
  10.           src='echobot.js'></script>
  11. </head>
  12. <body>
  13.   <div id='login' style='text-align: center'>
  14.     <form name='cred'>
  15.       <label for='jid'>JID:</label>
  16.       <input type='text' id='jid' value="sagan.me" />
  17.       <label for='pass'>Password:</label>
  18.       <input type='password' id='pass' />
  19.       <input type='button' id='connect' value='connect' />
  20.     </form>
  21.   </div>
  22.   <hr />
  23.   <div id='log'></div>
  24. </body>
  25. </html>

看echobot.js

  1. var BOSH_SERVICE =  '/xmpp-httpbind';
  2. var connection =  null;
  3.  
  4. function log (msg )
  5. {
  6.     $ ( '#log' ). append ( '<div></div>' ). append (document. createTextNode (msg ) );
  7. }
  8.  
  9. function onConnect ( status )
  10. {
  11.      if  ( status == Strophe. Status. CONNECTING )  {
  12.  log ( 'Strophe is connecting.' );
  13.      }  else  if  ( status == Strophe. Status. CONNFAIL )  {
  14.  log ( 'Strophe failed to connect.' );
  15.  $ ( '#connect' ). get ( 0 ). value =  'connect';
  16.      }  else  if  ( status == Strophe. Status. DISCONNECTING )  {
  17.  log ( 'Strophe is disconnecting.' );
  18.      }  else  if  ( status == Strophe. Status. DISCONNECTED )  {
  19.  log ( 'Strophe is disconnected.' );
  20.  $ ( '#connect' ). get ( 0 ). value =  'connect';
  21.      }  else  if  ( status == Strophe. Status. CONNECTED )  {
  22.  log ( 'Strophe is connected.' );
  23.  log ( 'ECHOBOT: Send a message to ' + connection. jid +
  24.       ' to talk to me.' );
  25.  
  26.  connection. addHandler (onMessage,  null'message'nullnull,   null );
  27.  connection. send ($pres ( ). tree ( ) );
  28.   var reply = $msg ( {to:  "ono@oogami.name", from: connection. jid, type:  'chat' } ). c ( "body" ). t ( "Test Chat Message" );
  29.         connection. send (reply. tree ( ) );
  30.      }
  31. }
  32.  
  33. function onMessage (msg )  {
  34.      var to = msg. getAttribute ( 'to' );
  35.      var from = msg. getAttribute ( 'from' );
  36.      var type = msg. getAttribute ( 'type' );
  37.      var elems = msg. getElementsByTagName ( 'body' );
  38.  
  39.      if  (type ==  "chat"  && elems. length  >  0 )  {
  40.   var body = elems [ 0 ];
  41.  
  42.  log ( 'ECHOBOT: I got a message from ' + from +  ': ' +
  43.      Strophe. getText (body ) );
  44.    
  45.   var reply = $msg ( {to: from, from: to, type:  'chat' } )
  46.             . cnode (Strophe. copyElement (body ) );
  47.  connection. send (reply. tree ( ) );
  48.  
  49.  log ( 'ECHOBOT: I sent ' + from +  ': ' + Strophe. getText (body ) );
  50.      }
  51.  
  52.      // we must return true to keep the handler alive.  
  53.      // returning false would remove it after it finishes.
  54.      return  true;
  55. }
  56.  
  57. $ (document ). ready ( function  ( )  {
  58.     connection =  new Strophe. Connection (BOSH_SERVICE );
  59.  
  60.      // Uncomment the following lines to spy on the wire traffic.
  61.      //connection.rawInput = function (data) { log('RECV: ' + data); };
  62.      //connection.rawOutput = function (data) { log('SEND: ' + data); };
  63.  
  64.      // Uncomment the following line to see all the debug output.
  65.      //Strophe.log = function (level, msg) { log('LOG: ' + msg); };
  66.  
  67.  
  68.     $ ( '#connect' ). bind ( 'click'function  ( )  {
  69.   var button = $ ( '#connect' ). get ( 0 );
  70.   if  (button. value ==  'connect' )  {
  71.      button. value =  'disconnect';
  72.  
  73.      connection. connect ($ ( '#jid' ). get ( 0 ). value,
  74.           $ ( '#pass' ). get ( 0 ). value,
  75.           onConnect );
  76.   }  else  {
  77.      button. value =  'connect';
  78.      connection. disconnect ( );
  79.   }
  80.      } );
  81. } );

将ono@oogami.name修改为一个测试Jabber帐号. 然后用浏览器打开echobot.html, 点击Connect按钮, Strophe就会匿名登录到刚刚建立的ejabber服务器( sagan.me ), 并向 "ono@oogami.name"这个帐号发送一条"Test Message"的信息.

另: 测试匿名登录向somebody@gtalk.com 发送消息失败, log里显示Gtalk服务器返回信息是503 error, Service-Unavailable, 但如果正常登录并添加Gtalk为好友的话则可以. Gtalk禁止了匿名用户向其发送消息? 我还在查资料中.

我准备用Javascript写一个简单的XMPP WEB匿名客户端, 实现允许访客直接与Gtalk和Facebook Chat通信等功能.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值