7

就像这个问题一样,我想从 PHP 生成一个 htpasswd 文件条目。但是,它必须是 APR1 (Apache) 样式,如原始答案(答案没有显示如何实现 APR1 样式)中所述,才能与 mod_dav_svn 一起使用。

我似乎找不到可以创建密码的有效实现。

我发现了这个(我忘记了现在在哪里):

function crypt_apr1_md5($plainpasswd) {
    $salt = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"), 0, 8);
    $len = strlen($plainpasswd);
    $text = $plainpasswd.'$apr1$'.$salt;
    $bin = pack("H32", md5($plainpasswd.$salt.$plainpasswd));
    for($i = $len; $i > 0; $i -= 16) { $text .= substr($bin, 0, min(16, $i)); }
    for($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(0) : $plainpasswd{0}; }
    $bin = pack("H32", md5($text));
    for($i = 0; $i < 1000; $i++) {
        $new = ($i & 1) ? $plainpasswd : $bin;
        if ($i % 3) $new .= $salt;
        if ($i % 7) $new .= $plainpasswd;
        $new .= ($i & 1) ? $bin : $plainpasswd;
        $bin = pack("H32", md5($new));
    }
    for ($i = 0; $i < 5; $i++) {
        $k = $i + 6;
        $j = $i + 12;
        if ($j == 16) $j = 5;
        $tmp = $bin[$i].$bin[$k].$bin[$j].$tmp;
    }
    $tmp = chr(0).chr(0).$bin[11].$tmp;
    $tmp = strtr(strrev(substr(base64_encode($tmp), 2)),
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
    return "$"."apr1"."$".$salt."$".$tmp;
}

但它不会生成有效密码。我认为这可能与 apache 的版本有关,但不确定。(我在 CENTOS 5 上运行)

4

5 回答 5

2

事实证明我犯了一个错误,这个函数实际上创建了有效的 APR1 htpasswd 条目。它们看起来确实与 Apache 创建的不同,但它们确实有效。

于 2009-07-28T21:58:54.087 回答
1

在 phpclasses.org 等网站上寻找现有的组件。一个例子:http ://www.phpclasses.org/browse/package/5066.html 。

于 2009-06-24T16:22:35.157 回答
1

谢谢!它就像一个魅力。

只是一个小注释:盐除了“a..z0..9”之外还可以包含“./”和“A..Z”,因此它与最后一行中的“翻译到”字符串是相同的字符串. 有时您还想设置盐,以创建可重现的结果,例如:

function crypt_apr1_md5( $plainpasswd, $salt = '' ) {
$translateTo = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
if ( $salt == '' ) { $salt = substr(str_shuffle($translateTo), 0, 8); }

...

$tmp = strtr(strrev(substr(base64_encode($tmp), 2)), "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", $translateTo);
return '$apr1$'.$salt.'$'.$tmp;
}

于 2010-06-15T09:33:58.453 回答
0

这可能有点 hacky,但是您是否考虑过使用 exec() 函数来调用生成 htpasswd 的命令?

于 2009-06-24T15:24:00.640 回答
0

看这个:

1:   private function crypt_apr1_md5($plainpasswd) { </br>
7:   for($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(o) : $plainpasswd{0}; } </br>
16:  $tmp = ''; </br>
于 2015-02-28T18:48:06.023 回答