Разработка PHP API с поддержкой протокола HTTPS

Раздел: -> Разработка API

Основное решение: Laravel REST API с HTTPS

Наиболее эффективный подход к созданию защищенного API на PHP - использование современного фреймворка Laravel. Он предоставляет встроенные средства для маршрутизации, контроллеров, валидации и обработки JSON. HTTPS обеспечивается на уровне веб-сервера (Nginx или Apache) или встроенного сервера для разработки с самоподписанным сертификатом.

Как создать защищенный REST API на Laravel и настроить HTTPS?

// routes/api.php
Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store']);

// app/Http/Controllers/UserController.php
public function index() {
    $users = User::all();
    return response()->json($users);
}

public function store(Request $request) {
    $validated = $request->validate(['name' => 'required', 'email' => 'required|email']);
    $user = User::create($validated);
    return response()->json($user, 201);
}

Api https php (api на php с https)

GET /api/users -> [{"id":1,"name":"John","email":"john@example.com"}]
POST /api/users -> {"id":2,"name":"Jane","email":"jane@example.com"}

Api php action (действия api в php)

Возможные проблемы:

  • HTTPS не включен: сертификат отсутствует или настроен неправильно - запросы возвращают ошибку 0 или отказ в соединении. Решение: использовать Let's Encrypt для продакшена или самоподписанный сертификат для разработки.
  • CORS: браузер блокирует кросс-доменные запросы. Нужно добавить middleware CORS (например, barryvdh/laravel-cors).
  • Валидация: неверные данные возвращают 422 с сообщениями.

Как написать простой HTTPS API на чистом PHP без фреймворков?

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

<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');

$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

if ($path === '/api/users' && $method === 'GET') {
    $users = [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']];
    echo json_encode($users);
} elseif ($path === '/api/users' && $method === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true);
    // Валидация и сохранение в БД
    echo json_encode(['status' => 'created', 'data' => $input]);
} else {
    http_response_code(404);
    echo json_encode(['error' => 'Not found']);
}
?>

Json api php (php: создание json api)

Типичные ошибки и их решение:

  • Отсутствие валидации - приводит к SQL-инъекциям; рекомендуется использовать PDO с подготовленными запросами.
  • Неправильная обработка CORS - браузер отклоняет запрос. Нужно корректно устанавливать заголовки Access-Control-Allow-Origin.
  • HTTPS настройка: в конфигурации веб-сервера (Apache/Nginx) необходимо указать пути к сертификату и ключу.

Как отправлять HTTPS запросы из PHP к внешним API с помощью Guzzle?

Библиотека Guzzle упрощает выполнение HTTP-запросов и автоматически обрабатывает SSL-сертификаты.

composer require guzzlehttp/guzzle

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://api.example.com', 'verify' => true]);
$response = $client->get('/endpoint', [
    'headers' => ['Authorization' => 'Bearer token'],
    'query' => ['param' => 'value']
]);
$data = json_decode($response->getBody(), true);

// POST с JSON
$response = $client->post('/resource', [
    'json' => ['key' => 'value']
]);

Php open api (открытое api на php)

Проблемы при использовании Guzzle:

  • SSL-ошибки в окружениях с самоподписанными сертификатами: установить 'verify' => false (только для разработки).
  • Тайм-ауты: добавить опцию 'timeout' => 10.
  • Ошибки HTTP (4xx,5xx): Guzzle выбрасывает исключения - их нужно перехватывать.

Как выполнить HTTPS запрос через cURL в PHP?

cURL - классический способ работы с HTTP в PHP. Он дает полный контроль над запросом.

$ch = curl_init('https://api.example.com/data');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_SSL_VERIFYHOST => 2,
    CURLOPT_CAINFO => '/path/to/cacert.pem',
    CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer token'],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode(['name' => 'value'])
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
    $error = curl_error($ch);
}
curl_close($ch);

Распространенные ошибки cURL:

  • SSL certificate problem: не указан путь к CA-сертификату или файл cacert.pem отсутствует. Скачать с https://curl.haxx.se/docs/caextract.html.
  • Неправильный метод: для POST забывают установить CURLOPT_POST.
  • Проблемы с кодировкой: ответ в gzip - добавить CURLOPT_ENCODING => ''.

Расширенные примеры работы с HTTPS в PHP API

Пример полного самописного API с JWT аутентификацией и HTTPS

Код включает генерацию и проверку JWT, middleware для авторизации. Сервер настроен на принудительное использование HTTPS через .htaccess.

Пример
// index.php (входной файл)
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$secret = 'your-secret-key';

// Middleware: проверка HTTPS
if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off') {
    header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
    exit;
}

// Middleware: проверка JWT для защищенных маршрутов
function authenticate() {
    $headers = getallheaders();
    $token = str_replace('Bearer ', '', $headers['Authorization'] ?? '');
    try {
        $decoded = JWT::decode($token, new Key($secret, 'HS256'));
        return $decoded;
    } catch (Exception $e) {
        http_response_code(401);
        echo json_encode(['error' => 'Unauthorized']);
        exit;
    }
}

// Маршрут для логина (без JWT)
if ($_SERVER['REQUEST_URI'] === '/api/login' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true);
    // Проверка учетных данных (упрощенно)
    if ($input['username'] === 'admin' && $input['password'] === 'pass') {
        $payload = [
            'iss' => 'localhost',
            'iat' => time(),
            'exp' => time() + 3600,
            'sub' => 1
        ];
        $token = JWT::encode($payload, $secret, 'HS256');
        echo json_encode(['token' => $token]);
    } else {
        http_response_code(401);
        echo json_encode(['error' => 'Invalid credentials']);
    }
    exit;
}

// Защищенный маршрут
if ($_SERVER['REQUEST_URI'] === '/api/profile' && $_SERVER['REQUEST_METHOD'] === 'GET') {
    $user = authenticate();
    // Вернуть данные пользователя
    echo json_encode(['user' => $user->sub]);
    exit;
}
# Ответ на POST /api/login с правильными данными
{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."}
# Ответ на GET /api/profile с заголовком Authorization: Bearer 
{"user":1}
# Ответ при отсутствии токена
{"error":"Unauthorized"}

Настройка встроенного PHP-сервера с самоподписанным сертификатом для тестирования

Для локальной разработки можно запустить PHP-сервер с SSL, используя самоподписанный сертификат.

Пример
# Генерация сертификата (однократно)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt -subj "/CN=localhost"

# Запуск сервера
php -S localhost:8000 -t public -c php.ini \
  --ssl-cert=server.crt --ssl-key=server.key
PHP Development Server started on https://localhost:8000
(Доступно в браузере с предупреждением о небезопасном соединении)

В коде API можно проверять переменную $_SERVER['HTTPS'], чтобы убедиться, что соединение защищено.

Пример использования middleware для принудительного HTTPS в Slim Framework

Пример
use Slim\Factory\AppFactory;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

$app = AppFactory::create();

$app->add(function (Request $request, $handler) {
    $uri = $request->getUri();
    if ($uri->getScheme() !== 'https') {
        $uri = $uri->withScheme('https');
        return (new \Slim\Psr7\Response(301))->withHeader('Location', (string)$uri);
    }
    return $handler->handle($request);
});

$app->get('/api/test', function (Request $request, Response $response) {
    $response->getBody()->write(json_encode(['status' => 'ok']));
    return $response->withHeader('Content-Type', 'application/json');
});

$app->run();
При запросе http://example.com/api/test происходит перенаправление на https://example.com/api/test

Логирование HTTPS-запросов с помощью Guzzle Middleware

Пример
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Log\LoggerInterface;

$logger = new Monolog\Logger('api');
$logger->pushHandler(new Monolog\Handler\StreamHandler('php://stdout'));

$stack = HandlerStack::create();
$stack->push(Middleware::log($logger, new GuzzleHttp\MessageFormatter(GuzzleHttp\MessageFormatter::SHORT)));

$client = new Client(['handler' => $stack, 'verify' => '/path/to/cacert.pem']);

$response = $client->get('https://api.secure.com/endpoint');
[2025-04-09 12:00:00] api.INFO: GET /endpoint HTTP/1.1 200 - -

API на PHP с HTTPS - comments

En
Api https php (php)