Как редактировать .htpasswd с помощью PHP? - PullRequest
7 голосов
/ 08 июня 2010

У меня есть защищенный каталог, куда может получить доступ только пользователь на .htpasswd, но иногда требуется, чтобы пользователь изменил пароль или имя пользователя, изменил пароль конкретного имени пользователя под своим именем

sample users
kevien : kka
mike : mike

И скажем, я хочу изменить кевьен на XYZ

И то же самое относится к паролю

Ответы [ 5 ]

7 голосов
/ 09 января 2012

Я изменил функцию, чтобы использовать все типы алгоритмов шифрования. Кто-то может найти это полезным:

/*
Function change password in htpasswd.
Arguments:
$user    > User name we want to change password to.
$newpass > New password
$type    > Type of cryptogrphy: DES, SHA, MD5. 
$salt    > Option: Add your custom salt (hashing string). 
           Salt is applied to DES and MD5 and must be in range 0-9A-Za-z
$oldpass > Option: Add more security, user must known old password to change it. 
           This option is not supported for DES and MD5 without salt!!!
$path    > Path to .htaccess file which contain the password protection. 
           Path to password file is obtained from this .htaccess file. 
*/  

function changePass($user, $newpass, $type="SHA", $salt="", $oldpass="", $path=".htaccess")
{
    switch ($type) {
        case "DES" :
            $salt = substr($salt,0,2);  // Salt must be 2 char range 0-9A-Za-z
            $newpass = crypt($newpass,$salt);
            if ($oldpass != null) {
                $oldpass = crypt($oldpass,$salt);
            }
            break;

        case "SHA" :
            $newpass = '{SHA}'.base64_encode(sha1($newpass, TRUE));
            if ($oldpass != null) {
                $oldpass = '{SHA}'.base64_encode(sha1($oldpass, TRUE));
            }
            break;

        case "MD5" :
            $salt = substr($salt,0,8);  //Salt must be max 8 char range 0-9A-Za-z
            $newpass = crypt_apr1_md5($newpass, $salt);
            if ($oldpass != null) {
                $oldpass = crypt_apr1_md5($oldpass, $salt);
            }
            break;

        default:
            return false;
            break;
    }

    $hta_arr = explode("\n", file_get_contents($path));

    foreach ($hta_arr as $line) {
        $line = preg_replace('/\s+/','',$line); // remove spaces
        if ($line) {
            $line_arr = explode('"', $line);
            if (strcmp($line_arr[0],"AuthUserFile") == 0) {
                $path_htaccess = $line_arr[1];
            }   
        }
    }  
    $htp_arr = explode("\n", file_get_contents($path_htaccess));

    $new_file = "";
    foreach ($htp_arr as $line) {
        $line = preg_replace('/\s+/', '', $line); // remove spaces
        if ($line) {
            list($usr, $pass) = explode(":", $line, 2);
            if (strcmp($user, $usr) == 0) {
                if ($oldpass != null) {
                    if ($oldpass == $pass) {
                        $new_file .= $user.':'.$newpass."\n";
                    } else {
                        return false;
                    }
                } else {
                    $new_file .= $user.':'.$newpass."\n";
                }
            } else {
                $new_file .= $user.':'.$pass."\n";
            }
        }
    }
    $f = fopen($path_htaccess,"w") or die("couldn't open the file");
    fwrite($f, $new_file);
    fclose($f);
    return true;
}

Функция для генерации Apache как MD5:

/**
 * @param string $password
 * @param string|null $salt
 * @ref https://stackoverflow.com/a/8786956
 */
function crypt_apr1_md5($password, $salt = null)
{
    if (!$salt) {
        $salt = substr(base_convert(bin2hex(random_bytes(6)), 16, 36), 1, 8);
    }
    $len = strlen($password);

    $text = $password . '$apr1$' . $salt;

    $bin = pack("H32", md5($password . $salt . $password));

    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) : $password[0];
    }

    $bin = pack("H32", md5($text));

    for ($i = 0; $i < 1000; $i++) {
        $new = ($i & 1) ? $password : $bin;

        if ($i % 3) {
            $new .= $salt;
        }

        if ($i % 7) {
            $new .= $password;
        }

        $new .= ($i & 1) ? $bin : $password;
        $bin = pack("H32", md5($new));
    }

    $tmp = '';

    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;
}

Демоверсия crypt_apr1_md5() доступна здесь .

Обратите внимание, что в Apache 2.4, bcrypt поддерживается , поэтому вы можете (и СЛЕДУЕТ) просто использовать password_hash() в более новых версиях Apache для этой цели.

4 голосов
/ 08 июня 2010

Ofc Это всего лишь пример, который прочитает ваш текущий файл, найдет данное имя пользователя и изменит либо пароль пользователя.

Имейте в виду, что этот код небезопасен, и вам все равно необходимо проанализировать имя пользователя и пароль, чтобы он не сломал ваш файл.

    $username = $_POST['user'];
    $password = $_POST['pass'];
    $new_username = $_POST['newuser'];
    $new_password = $_POST['newpass'];
    $action = $_POST['action'];
    //read the file into an array
    $lines = explode("\n", file_get_contents('.htpasswd'));

    //read the array and change the data if found
    $new_file = "";
    foreach($lines as $line)
    {
        $line = preg_replace('/\s+/','',$line); // remove spaces
        if ($line) {
            list($user, $pass) = split(":", $line, 2);
            if ($user == $username) {
                if ($action == "password") {
                    $new_file .= $user.':'.$new_password."\n";
                } else {
                    $new_file .= $new_username.':'.$pass."\n";
                }
            } else {
                $new_file .= $user.':'.$pass."\n";
            }
        }
    }

    //save the information
    $f=fopen(".htpasswd","w") or die("couldn't open the file");
    fwrite($f,$new_file);
    fclose($f);
4 голосов
/ 08 июня 2010

Не. Вместо этого сохраните свой authdb в базе данных, например, через mod_auth_mysql.

3 голосов
/ 08 июня 2010

Прогуглил "php generate htpasswd", получил эту статью: Как создать пароль для файла .htpasswd с помощью PHP .

Ключевая строка выглядит так:

$password = crypt($clearTextPassword, base64_encode($clearTextPassword));

Итак, я предполагаю, что вы прочитаете содержимое файла с помощью file_get_contents, проанализируете его в ассоциативный массив, измените соответствующие записи (зашифровав пароль, как показано выше), запишите массив обратно в строку и используйте file_put_contents чтобы записать файл обратно.

Однако это определенно не стандартная практика. Похоже, работа для базы данных. Если вы чувствуете странность в настройке целого сервера базы данных и ваш хост поддерживает его, SQLite может быть хорошим выбором.

0 голосов
/ 17 февраля 2015

На случай, если кто-то просто ищет рабочий скрипт, вот решение.

Это сценарий, опубликованный здесь Kavoir с небольшим изменением: http://www.kavoir.com/backyard/showthread.php?28-Use-PHP-to-generate-edit-and-update-htpasswd-and-htgroup-authentication-files

<?php
/*
 $pairs = array(
  'username' = 'password',
 );
*/

// Algorithm: SHA1

class Htpasswd {

private $file = '';

public function __construct($file) {
    if (file_exists($file)) {
        $this -> file = $file;
    } else {
        return false;
    }
}

private function write($pairs = array()) {
    $str = '';
    foreach ($pairs as $username => $password) {
        $str .= "$username:{SHA}$password\n";
    }
    file_put_contents($this -> file, $str);
}

private function read() {
    $pairs = array();
    $fh = fopen($this -> file, 'r');
    while (!feof($fh)) {
        $pair_str = str_replace("\n", '', fgets($fh));
        $pair_array = explode(':{SHA}', $pair_str);
        if (count($pair_array) == 2) {
            $pairs[$pair_array[0]] = $pair_array[1];
        }
    }
    return $pairs;
}

public function addUser($username = '', $clear_password = '') {
    if (!empty($username) && !empty($clear_password)) {
        $all = $this -> read();
      //  if (!array_key_exists($username, $all)) {
            $all[$username] = $this -> getHash($clear_password);
            $this -> write($all);
     //   }
    } else {
        return false;
    }
}

public function deleteUser($username = '') {
    $all = $this -> read();
    if (array_key_exists($username, $all)) {
        unset($all[$username]);
        $this -> write($all);
    } else {
        return false;
    }
}

public function doesUserExist($username = '') {
    $all = $this -> read();
    if (array_key_exists($username, $all)) {
        return true;
    } else {
        return false;
    }
}

private function getHash($clear_password = '') {
    if (!empty($clear_password)) {
        return base64_encode(sha1($clear_password, true));
    } else {
        return false;
    }
}

}  

Вы можете использовать этот скрипт как:

$htp = new Htpasswd('.htpasswd');
$htp -> addUser('username1', 'clearpassword1');  // this will add or edit the user
$htp -> deleteUser('username1');  
// check if a certain username exists
if ($htp -> doesUserExist('username1')) {
 // user exists
}  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...