Ниже — базовый пример кода для интеграции входа через Яндекс ID (OAuth 2.0) в PunBB. Это не готовый плагин «из коробки», а скелет, который нужно встроить в PunBB (например, в отдельный файл и вызовы в нужных местах). Учитывайте, что PunBB 1.4.x написан на PHP и имеет свою систему сессий и пользователей.
Важные оговорки перед кодом
- Нет официального плагина PunBB → Яндекс ID. Придётся писать свою обвязку.
- Безопасность:
client_secretникогда не храните в коде, который попадает в репозиторий; используйте переменные окружения. - Callback URL должен совпадать с тем, что указан в консоли разработчика Яндекс ID.
- Для PunBB нужно аккуратно работать с его функциями создания/загрузки пользователя и сессиями, чтобы не сломать встроенную авторизацию.
Шаг 1: Подготовка (в админке Яндекс ID)
В консоли разработчика Яндекса:
- Создайте приложение типа «Веб‑сервис».
- Укажите
Redirect URI, например:https://forum.rcl-radio.ru/login_yandex_callback.php. - Получите
client_idиclient_secret.
Шаг 2: Страница входа (кнопка «Войти через Яндекс»)
Пример простого файла login_yandex.php (или можно вставить кнопку в шаблон PunBB):
<?php
// login_yandex.php
require_once 'include/common.php';
require_once 'include/functions.php';
$client_id = 'ВАШ_CLIENT_ID';
$redirect_uri = urlencode('https://forum.rcl-radio.ru/login_yandex_callback.php');
$scope = urlencode('login:info'); // запрашиваем базовые данные
$auth_url = "https://oauth.yandex.ru/authorize?client_id={$client_id}&redirect_uri={$redirect_uri}&response_type=code&scope={$scope}";
header("Location: {$auth_url}");
exit;
?>
Добавьте ссылку на эту страницу в шаблон PunBB рядом с формой входа:
<a href="login_yandex.php" class="btn-yandex">Войти через Яндекс</a>
Шаг 3: Callback (обработка ответа от Яндекса)
Файл login_yandex_callback.php:
<?php
require_once 'include/common.php';
require_once 'include/functions.php';
$client_id = 'ВАШ_CLIENT_ID';
$client_secret = 'ВАШ_CLIENT_SECRET'; // лучше из env
$redirect_uri = 'https://forum.rcl-radio.ru/login_yandex_callback.php';
if (!isset($_GET['code'])) {
// ошибка: нет кода авторизации
message('Ошибка авторизации: нет кода от Яндекса.');
}
$code = $_GET['code'];
// Обмен кода на access_token
$token_url = 'https://oauth.yandex.ru/token';
$post_data = [
'grant_type' => 'authorization_code',
'code' => $code,
'client_id' => $client_id,
'client_secret' => $client_secret,
'redirect_uri' => $redirect_uri,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $token_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
$response = curl_exec($ch);
curl_close($ch);
if (!$response) {
message('Ошибка: не удалось получить токен от Яндекса.');
}
$token_data = json_decode($response, true);
if (!isset($token_data['access_token'])) {
message('Ошибка: в ответе от Яндекса нет access_token.');
}
$access_token = $token_data['access_token'];
// Получение данных пользователя
$info_url = 'https://login.yandex.ru/info?format=json';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $info_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: OAuth {$access_token}"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
$user_info = curl_exec($ch);
curl_close($ch);
$user_data = json_decode($user_info, true);
if (!$user_data || !isset($user_data['id'])) {
message('Ошибка: не удалось получить данные пользователя от Яндекса.');
}
// Теперь у нас есть данные пользователя из Яндекса
// Нужно либо найти пользователя в PunBB по email/логину, либо создать нового
$yandex_id = $user_data['id'];
$email = isset($user_data['default_email']) ? $user_data['default_email'] : '';
$login = isset($user_data['login']) ? $user_data['login'] : 'yandex_' . $yandex_id;
$display_name = isset($user_data['display_name']) ? $user_data['display_name'] : $login;
// Ищем пользователя в PunBB
$result = $db->query("SELECT id, username FROM {$db_prefix}users WHERE email = ? OR username = ?", $email, $login);
$row = $db->fetch_row($result);
if ($row) {
$user_id = (int)$row[0];
// Пользователь уже есть — логиним
punbb_login($user_id, false); // стандартная функция PunBB для входа
} else {
// Создаём нового пользователя
// Важно: пароль для таких пользователей можно не хранить или поставить случайный
$password = generate_random_password(); // нужна функция генерации
$salt = generate_salt(); // нужна функция генерации соли
$password_hash = sha1($salt . sha1($password)); // PunBB 1.4 использует SHA1+salt
$db->query(
"INSERT INTO {$db_prefix}users (username, password, salt, email, disp_name, show_img, last_visit, registered, group_id) VALUES (?, ?, ?, ?, ?, 0, " . time() . ", " . time() . ", 2)",
$login, $password_hash, $salt, $email, $display_name
);
$user_id = $db->insert_id();
// Опционально: сохранить yandex_id в отдельной таблице/поле, чтобы потом не создавать дубли
}
if ($user_id) {
punbb_login($user_id, false);
redirect('index.php', 'Вы успешно вошли через Яндекс!');
} else {
message('Не удалось войти или создать пользователя.');
}
?>
Примечание: функции
generate_random_password(),generate_salt()иpunbb_login()— это либо ваши хелперы, либо стандартные функции PunBB/вашей обвязки. В PunBB 1.4 логика хеширования пароля и создания пользователя может отличаться в разных форках/патчах, поэтому сверяйте с вашим кодом.
Как избежать дублей пользователей
Самый надёжный способ — хранить связь yandex_id → punbb_user_id в отдельной таблице, например:
CREATE TABLE pp_yandex_links (
yandex_id VARCHAR(255) NOT NULL,
user_id INT NOT NULL,
PRIMARY KEY (yandex_id)
);
Тогда при входе сначала ищите по yandex_id, и только если не нашли — создавайте нового пользователя.
Интеграция с политикой конфиденциальности (галочка согласия)
Если вы хотите требовать согласие с политикой при входе через Яндекс, проще всего сделать это на отдельной странице перед редиректом на Яндекс:
- Пользователь нажимает «Войти через Яндекс».
- Его перекидывает на
login_yandex_agree.php, где есть чекбокс «Нажимая „Войти через Яндекс“, вы соглашаетесь с Политикой конфиденциальности сайта». - Если галочка не стоит — показать ошибку.
- Если стоит — записать факт согласия (в сессию или в таблицу) и редиректить на
login_yandex.php.
Пример проверки чекбокса:
if (!isset($_POST['privacy_policy_accepted'])) {
message('Вы должны согласиться с Политикой конфиденциальности для входа через Яндекс.');
}
И форма:
<form method="post" action="login_yandex.php">
<label>
<input type="checkbox" name="privacy_policy_accepted" value="1">
Нажимая «Войти через Яндекс», вы соглашаетесь с <a href="/privacy.html">Политикой конфиденциальности сайта</a>.
</label>
<button type="submit">Продолжить вход через Яндекс</button>
</form>
Нюансы под ваш случай (PunBB 1.4.6 + префикс pp_)
- Все запросы к базе должны использовать
$db_prefix(в PunBB это глобальная переменная). Если у вас префиксpp_, то$db_prefixуже должен быть равенpp_. - Не меняйте структуру таблиц PunBB вручную без понимания последствий. Для связи с Яндекс ID лучше добавлять отдельную таблицу (как выше), а не менять существующие.
- Если вы планируете в будущем переезд на bbPress, то такую интеграцию лучше делать так, чтобы её было легко отключить или перенести логику.
Что ещё важно учесть с точки зрения закона и вашего контекста
- При регистрации через Яндекс вы собираете персональные данные (email, имя, ID). Это нужно отразить в политике конфиденциальности.
- Если вы прекращаете регистрацию новых пользователей (по ФЗ № 199‑ФЗ), то на странице
login_yandex_agree.phpможно дополнительно показывать сообщение: «Регистрация новых пользователей прекращена. Вход возможен только для существующих аккаунтов».
