我的ejabberd 2.1.2和 external_auth没有收到回复有问题。我已经检查了谷歌上的所有不同帖子和这里的问题,但仍然没有找到解决方案。
在我的/etc/ejabberd/ejabberd.cfg中,我有以下条目:
{auth_method, external}.
{extauth_program, "/tmp/auth.php"}.
上面提到的extauth_program可以在下面找到。我可以运行php文件作为'ejabberd'用户和文件创建/文件权限(日志文件)也不是问题。
#!/usr/bin/php
<?
$fh = fopen("php://stdin", 'r');
$stdout = fopen('php://stdout', 'w');
$fs = fopen("/tmp/auth-log.txt." . getmypid(), 'a');
if(!$fh){
die("Cannot open STDIN\n");
}
$users = array('user1'=>'password1', 'user2'=>'password2');
do{
$lenBytes = fgets($fh, 3);
$len = unpack('n', $lenBytes);
$len = $len[1];
if($len<1) continue;
$msg = fgets($fh, $len+1);
$toks=explode(':',$msg);
fwrite($fs, $msg . "\n");
$method = array_shift($toks);
fwrite($fs, "$method\n");
$result = false;
switch($method){
case 'auth':
list($username, $server, $password) = $toks;
$password = trim($password);
fwrite($fs, "checking user: $username and password $password\n");
if($users[$username] == $password){
fwrite($fs, "password match\n");
$result = true;
}else{
$result = false;
}
break;
case 'isuser':
list($username, $server) = $toks;
if(isset($users[$username])){
$result = true;
}else{
$result = false;
}
break;
default:
$result = false;
}
$message = @pack("nn", 2, $result);
fwrite($stdout, $message);
$dump = @unpack("nn", $message);
$dump = $dump["n"];
fwrite($fs, $dump . "\n");
flush();
} while(true);
?>
当我启动xjabberd并尝试连接'user1@example.com'和密码:'password1'时,需要花费相当长的时间,最终会失败。在日志文件中,我看到从上面的PHP脚本生成的以下条目。当从客户端到服务器的连接发生时,这些几乎立即发生。
auth:user1:example.com:password1
auth
checking user: user1 and password password1
password match
2
在/var/log/ejabberd/ejabberd.log中,我有以下条目:
=INFO REPORT==== 2011-02-20 01:15:26 ===
I(<0.557.0>:ejabberd_c2s:587) : ({socket_state,tls,{tlssock,#Port<0.2820>,#Port<0.2844>},<0.556.0>}) Failed authentication for user1@example.com
=ERROR REPORT==== 2011-02-20 01:15:36 ===
E(<0.365.0>:extauth:80) : extauth call '["auth","user1@example.com",
"example.com","password1"]' didn't receive response
=INFO REPORT==== 2011-02-20 01:15:36 ===
I(<0.559.0>:ejabberd_c2s:587) : ({socket_state,tls,{tlssock,#Port<0.2846>,#Port<0.2848>},<0.558.0>}) Failed authentication for user1@example.com@example.com
=INFO REPORT==== 2011-02-20 01:15:37 ===
I(<0.553.0>:ejabberd_listener:232) : (#Port<0.2850>) Accepted connection {{10,1,1,3},55051} -> {{10,130,11,243},5222}
=ERROR REPORT==== 2011-02-20 01:15:50 ===
E(<0.365.0>:extauth:80) : extauth call '["auth","user1","example.com",
"password1"]' didn't receive response
=INFO REPORT==== 2011-02-20 01:15:50 ===
I(<0.561.0>:ejabberd_c2s:587) : ({socket_state,tls,{tlssock,#Port<0.2850>,#Port<0.2852>},<0.560.0>}) Failed authentication for user1@example.com
=INFO REPORT==== 2011-02-20 01:15:51 ===
I(<0.553.0>:ejabberd_listener:232) : (#Port<0.2854>) Accepted connection {{10,1,1,3},55052} -> {{10,130,11,243},5222}
=ERROR REPORT==== 2011-02-20 01:16:03 ===
E(<0.365.0>:extauth:80) : extauth call '["auth","user1@example.com",
"example.com","password1"]' didn't receive response
=INFO REPORT==== 2011-02-20 01:16:03 ===
I(<0.563.0>:ejabberd_c2s:587) : ({socket_state,tls,{tlssock,#Port<0.2854>,#Port<0.2856>},<0.562.0>}) Failed authentication for user1@example.com@example.com
任何有助于解决此问题的帮助将不胜感激。提前谢谢!
答案 0 :(得分:1)
行前:
$message = @pack("nn", 2, $result);
写:
$result = ($result) ? 1 : 0;
答案 1 :(得分:1)
花了1天时间试图获得工作ejabberd授权
在从stdin读取时阻塞进程时基本出现问题。它会在请求字符串结束时被阻塞,直到客户端因超时而断开连接
以下是从符号读取符号的非块符号解决方案:
function non_block_read($fd, &$data) {
$read = array($fd);
$write = array();
$except = array();
$result = stream_select($read, $write, $except, 0);
if($result === false) {
throw new Exception('stream_select failed');
}
if($result === 0) return false;
$data.= stream_get_line($fd, 1);
return true;
}
这里的守护进程代码也可以进行终身阅读循环。
$fh = fopen("php://stdin", 'r');
$fhout = fopen("php://stdout", 'w');
$pdo = new PDO('mysql:host='.$host.';dbname='.$db, $user,$pass);
if(!$fh){
die("Cannot open STDIN\n");
}
$aStr='';
$collect=false;
do {
if (!non_block_read($fh,$aStr)) {
if (strlen($aStr) > 0) {
$toAuth = substr(trim($aStr),1);
checkAuth($toAuth,$pdo,$fhout);
$aStr='';
}
else sleep (1);
}
}
while (true);
一些解释:checkAuth - 任何实现&#39; auth&#39;和&#39; isuser&#39;处理程序。
sleep(1) - 逃避CPU负载的简单方法
第一个符号 - 在邮件之前添加的服务符号,它因客户而异,所以我只是将其删除
这是回复代码。回复 - 真实|虚假价值观。
$message = @pack("nn", 2, $result);
fwrite($stdout, $message);
flush();
享受。