Ejabberd单一请求登录

时间:2011-12-15 16:07:38

标签: erlang single-sign-on xmpp ejabberd

我有一个工作的Ejabberd服务器(版本2.1.9)和我的客户端应用程序运行正常,但我希望修改应用程序的XMPP客户端连接到Ejabberd的方式,以减少它们之间的请求/响应的数量,因为它适用于移动环境,我希望减少初始连接时间。

我查找了XMPP协议规范(RFC 6120)和一些协议扩展(XEP),即XEP-0305 Quickstart,但协议本身并未指定单个请求登录和快速入门扩展虽然旨在减少请求的数量并不足以减少我正在寻找的时间。

在搜索并找不到任何解决方案后,我开始修改客户端和服务器,并希望现在完成以下操作作为概念验证:

//Client Request
<?xml version='1.0'?>
<stream:stream ... user='user' pass='pass'>

//Server Response
<?xml version='1.0'?>
<stream:stream ... success='1'>

我已经设法相应地修改了我的客户端和Ejabberd服务器,似乎它们连接成功,但是客户端在建立会话后做出的任何请求都没有得到服务器的响应。我使用Wireshark检查TCP连接客户端和服务器端:客户端打开并发送请求,服务器端也打开并收到请求,但是当我尝试发送响应时,它不是发送。

我只修改了文件ejabberd_c2s.erl,更改内容如下:

//init function
...
%% changed the first state of the fsm to point to quickstart
%%          {ok, wait_for_stream, #state{socket = Socket1,
            {ok, wait_for_quickstart, #state{socket = Socket1,
...

//wait_for_quickstart function
...
case resource_conflict_action(U, StateData#state.server, R) of
  closenew ->
    send_header(StateData, Server, "1.0", DefaultLang, "0"),
    send_trailer(StateData),
    {stop, normal, StateData};
    {accept_resource, R2} ->
      JID = jlib:make_jid(U, StateData#state.server, R2),
      allow = acl:match_rule(Server,c2s,JID),   
      case ejabberd_auth:check_password(U, Server, P) of
        true ->
          send_header(StateData, Server, "1.0", DefaultLang, "1"),
          change_shaper(StateData, JID),
          {Fs, Ts} = ejabberd_hooks:run_fold(
            roster_get_subscription_lists,
            StateData#state.server,
            {[], []},
            [U, StateData#state.server]),
          LJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)),
          Fs1 = [LJID | Fs],
          Ts1 = [LJID | Ts],
          PrivList =
            ejabberd_hooks:run_fold(
            privacy_get_user_list, 
            StateData#state.server,
            #userlist{},
           [U, StateData#state.server]),
         SID = {now(), self()},
         Conn = get_conn_type(StateData),
         Info = [{ip, StateData#state.ip},
         {conn, Conn},
         {auth_module, StateData#state.auth_module}],
         ejabberd_sm:open_session(SID, U, StateData#state.server, R, Info),
         NewStateData =
           StateData#state{
             user = U,
             resource = R2,
             jid = JID,
             sid = SID,
             conn = Conn,
             auth_module = ejabberd_auth_internal,
             authenticated = true,
             pres_f = ?SETS:from_list(Fs1),
             pres_t = ?SETS:from_list(Ts1),
             privacy_list = PrivList},
           fsm_next_state_pack(session_established,
           NewStateData);
        _ ->
          %%auth fail
          end
end.

只是为了澄清:初始客户端身份验证请求和服务器响应正在正常传输,后续请求也正在传输,但没有响应。

我忽略了什么?

提前致谢

1 个答案:

答案 0 :(得分:1)

@ Nuno-Freitas确实这就是失败的原因,感谢您的帮助。

我添加了代码:

R1 = xml:get_attr_s("r",Attrs),
R = case jlib:resourceprep(R1) of
      error -> error;
      "" ->
        lists:concat([randoms:get_string() | tuple_to_list(now())]);
        Resource -> Resource
    end,

这使得服务器响应我的请求,但还有其他问题:<presence/>标记在服务器上中断,因为#state.lang未定义,所以我必须在wait_for_quickstart中定义它{1}}函数,现在我在XMPP客户端服务器上有一个单点登录概念验证。