← Назад к вопросам

Есть ли код, который можешь показать?

1.2 Junior🔥 182 комментариев
#Опыт и карьера

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Конечно, покажу реальный код, который иллюстрирует несколько ключевых концепций PHP и современного Backend-разработки. Это будет модуль аутентификации пользователя с использованием Object-Oriented Programming (OOP), взаимодействием с базой данных через PDO, и реализацией JWT (JSON Web Token) для безопасного API. Этот код демонстрирует структуру, безопасность и профессиональные практики.

Пример: Класс аутентификации пользователя с JWT

<?php

declare(strict_types=1);

namespace App\Security;

use PDO;
use RuntimeException;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

/**
 * Класс AuthService отвечает за регистрацию, логин и верификацию пользователей через JWT.
 * Использует PDO для безопасной работы с базой данных и библиотеку firebase/php-jwt.
 */
class AuthService
{
    private PDO $db;
    private string $jwtSecretKey;
    private string $jwtAlgorithm = 'HS256';

    public function __construct(PDO $db, string $jwtSecretKey)
    {
        $this->db = $db;
        $this->jwtSecretKey = $jwtSecretKey;
    }

    /**
     * Регистрация нового пользователя.
     * @param string $email
     * @param string $password
     * @return array Возвращает массив с ID пользователя и статусом.
     * @throws RuntimeException Если пользователь уже существует или произошла ошибка БД.
     */
    public function register(string $email, string $password): array
    {
        // Проверка существования пользователя
        $stmt = $this->db->prepare("SELECT id FROM users WHERE email = :email");
        $stmt->execute([':email' => $email]);
        if ($stmt->fetch()) {
            throw new RuntimeException('Пользователь с таким email уже существует.');
        }

        // Создание хэша пароля с использованием современного алгоритма bcrypt
        $passwordHash = password_hash($password, PASSWORD_BCRYPT);

        // Вставка нового пользователя в БД
        $stmt = $this->db->prepare("INSERT INTO users (email, password_hash) VALUES (:email, :password_hash)");
        $stmt->execute([
            ':email' => $email,
            ':password_hash' => $passwordHash
        ]);

        $userId = (int)$this->db->lastInsertId();
        return ['user_id' => $userId, 'status' => 'registered'];
    }

    /**
     * Аутентификация пользователя и генерация JWT токена.
     * @param string $email
     * @param string $password
     * @return string Возвращает JWT токен для дальнейшего использования в API.
     * @throws RuntimeException Если аутентификация не успешна.
     */
    public function login(string $email, string $password): string
    {
        $stmt = $this->db->prepare("SELECT id, password_hash FROM users WHERE email = :email");
        $stmt->execute([':email' => $email]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$user || !password_verify($password, $user['password_hash'])) {
            throw new RuntimeException('Неверный email или пароль.');
        }

        // Генерация payload для JWT с пользовательскими данными и временем жизни
        $payload = [
            'user_id' => (int)$user['id'],
            'email' => $email,
            'iat' => time(), // Issued At: время создания токена
            'exp' => time() + (60 * 60) // Expiration: токен живёт 1 час
        ];

        // Генерация и возврат JWT токена
        return JWT::encode($payload, $this->jwtSecretKey, $this->jwtAlgorithm);
    }

    /**
     * Верификация и декодирование JWT токена из заголовка Authorization.
     * @param string $authHeader Значение заголовка "Bearer <token>"
     * @return array Возвращает декодированный payload токена.
     * @throws RuntimeException Если токен невалидный, просрочен или заголовок отсутствует.
     */
    public function verifyToken(string $authHeader): array
    {
        if (!preg_match('/Bearer\s+(.*)$/', $authHeader, $matches)) {
            throw new RuntimeException('Отсутствует или некорректный Authorization заголовок.');
        }

        $jwt = $matches[1];

        try {
            // Декодирование и верификация токена с использованием секретного ключа
            $decoded = JWT::decode($jwt, new Key($this->jwtSecretKey, $this->jwtAlgorithm));
            return (array)$decoded;
        } catch (\Exception $e) {
            throw new RuntimeException('Невалидный или просроченный JWT токен: ' . $e->getMessage());
        }
    }
}

Пример использования класса в контроллере API (например, для endpoint /api/login)

<?php

declare(strict_types=1);

namespace App\Controller;

use App\Security\AuthService;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class AuthController
{
    private AuthService $authService;

    public function __construct(AuthService $authService)
    {
        $this->authService = $authService;
    }

    /**
     * Обработка POST запроса на /api/login
     */
    public function login(ServerRequestInterface $request): ResponseInterface
    {
        $body = $request->getParsedBody(); // Предполагается, что используется PSR-7

        $email = $body['email'] ?? '';
        $password = $body['password'] ?? '';

        try {
            $jwtToken = $this->authService->login($email, $password);

            // Возвращаем успешный ответ с токеном в формате JSON
            $response = new JsonResponse([
                'success' => true,
                'token' => $jwtToken,
                'message' => 'Аутентификация успешна.'
            ]);
            return $response->withHeader('Content-Type', 'application/json');

        } catch (RuntimeException $e) {
            // Возвращаем ошибку клиента в формате JSON
            return new JsonResponse([
                'success' => false,
                'message' => $e->getMessage()
            ], 401); // HTTP статус 401 Unauthorized
        }
    }
}

Ключевые моменты, демонстрируемые в этом коде:

  • Современный PHP (strict_types=1): Использование строгой типизации для повышения надежности.
  • Объектно-ориентированный подход: Логика инкапсулирована в классе AuthService, что обеспечивает повторное использование и тестируемость.
  • Безопасность:
    * **Хэширование паролей**: Используется `password_hash()` с алгоритмом `PASSWORD_BCRYPT`, который является текущим стандартом.
    * **JWT (JSON Web Tokens)**: Токены используются для stateless аутентификации в API, содержат payload и защищены секретным ключом.
    * **PDO (PHP Data Objects)**: Для всех SQL операций используется подготовленные запросы (`prepare`/`execute`), что предотвращает **SQL Injection**.
  • Профессиональная структура:
    * Четкое разделение ответственности: Сервис (`AuthService`) обрабатывает бизнес-логику, Контроллер (`AuthController`) — HTTP взаимодействие.
    * Использование исключений (`RuntimeException`) для обработки ошибок и чистого управления потоком.
    * Предполагается использование **PSR-7** (`ServerRequestInterface`, `ResponseInterface`) для стандартизации HTTP, что характерно для современных фреймворков (Symfony, Slim).
  • Практики реального мира:
    * Токены имеют время жизни (`exp`), что важно для безопасности.
    * Метод `verifyToken` предназначен для middleware, который будет проверять токен перед каждым защищенным API запросом.

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