PHP
#bitrix#ajax#php#security#csrf#ajax.php

Безопасный AJAX endpoint через /bitrix/services/main/ajax.php

Создание безопасного AJAX-эндпоинта через стандартный механизм Bitrix с проверкой CSRF, прав доступа и валидацией данных.

Как использовать

  1. Скопируйте нужный фрагмент кода.
  2. Вставьте в свой проект и при необходимости измените под задачу.
  3. Проверьте зависимости и окружение (версии, переменные).

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

use Bitrix\Main\Loader;
use Bitrix\Main\Application;
use Bitrix\Main\Context;

/**
 * Обработчик AJAX через /bitrix/services/main/ajax.php
 * Регистрируется в /local/php_interface/init.php
 */

// Регистрируем обработчик
AddEventHandler('main', 'OnBeforeLocalRedirect', function(&$url, $skip_security_check, $external) {
    // Это не наш случай, просто возвращаем
});

// Создаём собственный обработчик через стандартный механизм
// В файле /local/ajax/custom_handler.php

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}

use Bitrix\Main\Application;
use Bitrix\Main\Loader;

// Подключаем модули
Loader::includeModule('main');
Loader::includeModule('iblock'); // если нужен

// Получаем запрос
$request = Application::getInstance()->getContext()->getRequest();

// Проверяем CSRF токен
if (!check_bitrix_sessid()) {
    header('Content-Type: application/json');
    echo json_encode(['success' => false, 'error' => 'Invalid CSRF token']);
    die();
}

// Проверяем метод запроса
if ($request->getRequestMethod() !== 'POST') {
    header('Content-Type: application/json');
    echo json_encode(['success' => false, 'error' => 'Only POST allowed']);
    die();
}

// Получаем действие
$action = $request->get('action');

// Обработка действий
switch ($action) {
    case 'update_element':
        // Проверяем права доступа
        global $USER;
        if (!$USER->IsAuthorized() || !$USER->IsAdmin()) {
            header('Content-Type: application/json');
            echo json_encode(['success' => false, 'error' => 'Access denied']);
            die();
        }
        
        // Получаем и валидируем данные
        $elementId = (int)$request->get('element_id');
        $name = trim($request->get('name'));
        
        if ($elementId <= 0 || empty($name)) {
            header('Content-Type: application/json');
            echo json_encode(['success' => false, 'error' => 'Invalid parameters']);
            die();
        }
        
        // Выполняем действие
        Loader::includeModule('iblock');
        $el = new CIBlockElement;
        $result = $el->Update($elementId, ['NAME' => $name]);
        
        if ($result) {
            header('Content-Type: application/json');
            echo json_encode(['success' => true, 'message' => 'Updated']);
        } else {
            header('Content-Type: application/json');
            echo json_encode(['success' => false, 'error' => $el->LAST_ERROR]);
        }
        break;
        
    default:
        header('Content-Type: application/json');
        echo json_encode(['success' => false, 'error' => 'Unknown action']);
}

die();

Usage:

// На фронтенде (JavaScript)
// Отправка запроса
fetch('/local/ajax/custom_handler.php', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams({
        action: 'update_element',
        element_id: 123,
        name: 'New Name',
        sessid: BX.bitrix_sessid() // CSRF токен из Bitrix
    })
})
.then(response => response.json())
.then(data => {
    if (data.success) {
        console.log('Success');
    } else {
        console.error('Error:', data.error);
    }
});

Notes:

⚠️ Всегда проверяйте check_bitrix_sessid() для защиты от CSRF. Ограничивайте методы запросов (только POST для изменяющих операций). Проверяйте права доступа через $USER->IsAuthorized() и $USER->IsAdmin(). Валидируйте все входящие данные. Используйте die() после отправки ответа. Файл должен быть в /local/ajax/ и начинаться с проверки B_PROLOG_INCLUDED.