Для повышения безопасности WordPress сайтов часто применяются различные методы аутентификации. Одним из относительно редких, но очень надежных способов является авторизация пользователей с помощью SSH ключей. В этой статье мы подробно разберем, как реализовать авторизацию по SSH ключу в WordPress, рассмотрим необходимые шаги настройки, а также покажем примеры кода для расширения стандартных возможностей.
Почему стоит использовать SSH ключи для авторизации в WordPress
Стандартная авторизация по логину и паролю имеет множество уязвимостей — от перебора пароля до фишинга. SSH ключи — это пара криптографических ключей (приватного и публичного), которые позволяют надежно подтверждать личность пользователя без необходимости ввода пароля.
Использование SSH ключей для входа в WordPress предоставляет следующие преимущества:
- Устойчивость к перебору паролей и brute force атакам.
- Отсутствие необходимости запоминать и вводить пароль.
- Возможность интеграции с системами управления ключами и аппаратными токенами.
Хотя WordPress из коробки не поддерживает такую схему, с помощью кастомных решений и плагинов ее можно реализовать.
Общая схема авторизации по SSH ключу в WordPress
Для реализации авторизации по SSH ключу нам нужно:
- Сгенерировать пару ключей SSH (приватный и публичный) для пользователя.
- Сохранить публичный ключ в базе данных WordPress, связав его с конкретным пользователем.
- При попытке входа пользователь предоставляет подпись, созданную приватным ключом.
- Сервер проверяет подпись с помощью публичного ключа пользователя и, если проверка успешна, аутентифицирует пользователя.
Важный момент — реализация протокола обмена и подписи может быть построена на базе REST API WordPress.
Пример реализации: добавляем поле публичного ключа в профиль пользователя
Для начала добавим в профиль пользователя поле для хранения публичного SSH ключа.
add_action('show_user_profile', 'wpauth_show_ssh_key_field');
add_action('edit_user_profile', 'wpauth_show_ssh_key_field');
function wpauth_show_ssh_key_field($user) {
?>
<h3>SSH Public Key</h3>
<table class="form-table">
<tr>
<th><label for="wpauth_ssh_key">Публичный SSH ключ</label></th>
<td>
<textarea name="wpauth_ssh_key" id="wpauth_ssh_key" rows="5" cols="50"><?php echo esc_textarea(get_user_meta($user->ID, 'wpauth_ssh_key', true)); ?></textarea><br>
<span class="description">Введите ваш публичный SSH ключ для авторизации по ключу.</span>
</td>
</tr>
</table>
<?php
}
add_action('personal_options_update', 'wpauth_save_ssh_key_field');
add_action('edit_user_profile_update', 'wpauth_save_ssh_key_field');
function wpauth_save_ssh_key_field($user_id) {
if (!current_user_can('edit_user', $user_id)) {
return false;
}
update_user_meta($user_id, 'wpauth_ssh_key', sanitize_textarea_field($_POST['wpauth_ssh_key']));
}
Этот код добавляет в профиль пользователя поле для ввода публичного SSH ключа и сохраняет его в мета данных пользователя.
Реализация проверки подписи и авторизации через REST API
Создадим кастомный endpoint REST API для авторизации. Клиент будет отправлять имя пользователя, сообщение и подпись, а сервер проверит подпись с помощью публичного ключа.
add_action('rest_api_init', function () {
register_rest_route('wpauth/v1', '/ssh-login', array(
'methods' => 'POST',
'callback' => 'wpauth_ssh_login_callback',
'permission_callback' => '__return_true',
));
});
function wpauth_ssh_login_callback(WP_REST_Request $request) {
$username = $request->get_param('username');
$message = $request->get_param('message');
$signature = $request->get_param('signature');
if (empty($username) || empty($message) || empty($signature)) {
return new WP_Error('missing_params', 'Отсутствуют необходимые параметры', array('status' => 400));
}
$user = get_user_by('login', $username);
if (!$user) {
return new WP_Error('invalid_user', 'Пользователь не найден', array('status' => 404));
}
$pub_key = get_user_meta($user->ID, 'wpauth_ssh_key', true);
if (empty($pub_key)) {
return new WP_Error('no_pubkey', 'Публичный SSH ключ не задан', array('status' => 403));
}
// Проверка подписи
$verified = wpauth_verify_ssh_signature($pub_key, $message, $signature);
if (!$verified) {
return new WP_Error('invalid_signature', 'Подпись не прошла проверку', array('status' => 403));
}
// Авторизация пользователя
wp_set_current_user($user->ID);
wp_set_auth_cookie($user->ID);
return array('success' => true, 'message' => 'Авторизация успешна');
}
/**
* Проверка подписи SSH
* @param string $pub_key - публичный ключ SSH
* @param string $message - исходное сообщение
* @param string $signature - подпись, закодированная base64
* @return bool
*/
function wpauth_verify_ssh_signature($pub_key, $message, $signature) {
$pubkey_res = ssh2_publickey_init($pub_key); // Внимание: в PHP нет стандартной функции ssh2_publickey_init
// Вместо этого используем openssl для проверки подписи, если ключ в формате RSA
$pubkey_res = openssl_pkey_get_public($pub_key);
if (!$pubkey_res) {
return false;
}
$decoded_signature = base64_decode($signature);
$result = openssl_verify($message, $decoded_signature, $pubkey_res, OPENSSL_ALGO_SHA256);
openssl_free_key($pubkey_res);
return ($result === 1);
}
Обратите внимание, что для проверки подписей SSH ключами нужно использовать подходящий формат ключа и алгоритмы. В большинстве случаев публичный SSH ключ в формате OpenSSH нужно конвертировать в PEM для работы с OpenSSL. Для этого можно воспользоваться утилитой ssh-keygen:
ssh-keygen -f id_rsa.pub -e -m pem > id_rsa_pub.pem
На клиенте подпись создается приватным ключом, например с помощью ssh-keygen или библиотек на выбранном языке программирования.
Пример клиентского запроса для авторизации
Пример на JavaScript с использованием Web Crypto API для подписи сообщения:
async function wpauthSignMessage(privateKeyPem, message) {
// Здесь нужна реализация импорта ключа и подписи, что достаточно сложно для SSH ключей,
// обычно используется готовая библиотека для SSH или криптографии.
}
Далее отправляем POST-запрос на endpoint /wp-json/wpauth/v1/ssh-login с параметрами username, message и signature.
Альтернативные решения и готовые плагины
Реализация авторизации по SSH ключам в WordPress — задача нетривиальная, особенно если требуется интеграция с существующими инструментами. Можно рассмотреть следующие варианты:
- Использовать плагин Clearfy Pro для усиления безопасности и настройки нестандартных схем аутентификации.
- Разработать кастомный плагин на базе приведенного примера, расширив функционал для поддержки разных алгоритмов подписи.
- Интегрировать WordPress с внешними системами аутентификации, поддерживающими SSH ключи, например через LDAP или PAM.
Резюме и советы по внедрению
Авторизация по SSH ключу — надежный способ повысить безопасность вашего WordPress сайта, особенно если у вас есть пользователи с высокими правами. Однако этот метод требует аккуратной настройки и тестирования, а также продуманной UX-части для удобства пользователей.
Если вы планируете внедрять такую схему, рекомендуем:
- Настроить безопасное хранение публичных ключей пользователей.
- Обеспечить простой и понятный интерфейс для добавления ключей в профиль.
- Тщательно протестировать проверку подписей и обработку ошибок.
- Рассмотреть возможность интеграции с двуфакторной аутентификацией для дополнительной безопасности.
Таким образом, вы сможете создать современную, безопасную и удобную систему авторизации для своего WordPress сайта.