bitrix-sessions

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Bitrix Sessions

Bitrix 会话

Directly accessing
$_SESSION
breaks non-functional modes (
readonly
, virtual session, separated session) and tests. Use the Session API.
php
use Bitrix\Main\Application;

$session = Application::getInstance()->getSession();

if (!$session->has('cart'))
{
    $session->set('cart', ['items' => []]);
}

$session['cart']['items'][] = $productId;
$session['cart'] = $cart; // set via ArrayAccess

$session->remove('flash_message');
$session->clear();          // remove everything
Interface —
Bitrix\Main\Session\SessionInterface
+
ArrayAccess
.
直接访问
$_SESSION
会破坏非功能模式(
readonly
、虚拟会话、分离会话)并影响测试。请使用Session API
php
use Bitrix\Main\Application;

$session = Application::getInstance()->getSession();

if (!$session->has('cart'))
{
    $session->set('cart', ['items' => []]);
}

$session['cart']['items'][] = $productId;
$session['cart'] = $cart; // 通过ArrayAccess赋值

$session->remove('flash_message');
$session->clear();          // 清除所有会话数据
接口——
Bitrix\Main\Session\SessionInterface
+
ArrayAccess

Kernel Session (hot)

内核会话(高频数据)

For a small amount of fast data that the kernel accesses almost every hit:
php
$kernelSession = Application::getInstance()->getKernelSession();
$kernelSession->set('UF_LAST_LOGIN', time());
In
separated
mode, the kernel stores the hot fragment in encrypted cookies — making authorization/CSRF fast without accessing backend storage.
适用于内核几乎每次请求都会访问的少量快速数据:
php
$kernelSession = Application::getInstance()->getKernelSession();
$kernelSession->set('UF_LAST_LOGIN', time());
separated
模式下,内核会将高频片段存储在加密Cookie中——无需访问后端存储即可快速完成授权/CSRF验证。

SessionLocalStorage — "Session Cache"

SessionLocalStorage ——「会话缓存」

Using
$session->set(...)
for cart cache or temporary calculations is bad: long values block the hit and slow down parallel AJAX. Since
main 20.5.400
, there is an isolated container tied to
session_id()
:
php
$local = Application::getInstance()->getLocalSession('cart');

if (!isset($local['productIds']))
{
    $local->set('productIds', [1, 2, 3]);
    $local->set('total', 42);
}

$ids = $local->get('productIds');
  • Stored in the cache from the
    cache
    section in
    .settings.php
    (not in
    $_SESSION
    ).
  • Automatically saved at the end of the hit.
  • With file cache,
    $_SESSION
    is used internally so that GC correctly cleans up stale data.
Use for: carts, temporary filters, wizards, UI drafts.
使用
$session->set(...)
存储购物车缓存或临时计算数据并不合适:过长的值会阻塞请求并拖慢并行AJAX。从
main 20.5.400
版本开始,新增了与
session_id()
绑定的独立容器:
php
$local = Application::getInstance()->getLocalSession('cart');

if (!isset($local['productIds']))
{
    $local->set('productIds', [1, 2, 3]);
    $local->set('total', 42);
}

$ids = $local->get('productIds');
  • 存储在
    .settings.php
    cache
    配置段指定的缓存中(而非
    $_SESSION
    )。
  • 请求结束时自动保存。
  • 使用文件缓存时,内部会借助
    $_SESSION
    确保垃圾回收(GC)能正确清理过期数据。
适用场景:购物车、临时筛选器、向导、UI草稿。

Session Modes

会话模式

Read-only (non-blocking)

只读模式(非阻塞)

Suitable for AJAX where writing is not needed — removes the write lock:
php
// before including prolog
define('BX_SECURITY_SESSION_READONLY', true);

require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';
After this:
  • Session is read from redis/memcache/db without
    flock
    /SETNX — parallel AJAX requests don't wait for each other.
  • Changes will not be saved at the end of the hit.
Good for read-only endpoints (search, suggestions, counters).
适用于无需写入操作的AJAX请求——移除写入锁:
php
// 引入prolog前定义
define('BX_SECURITY_SESSION_READONLY', true);

require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';
设置后:
  • 会话会从Redis/Memcache/数据库读取,无需
    flock
    /SETNX——并行AJAX请求无需互相等待。
  • 请求结束时不会保存任何修改。
适合只读接口(搜索、联想建议、计数器)。

Virtual (in-memory)

虚拟模式(内存中)

php
define('BX_SECURITY_SESSION_VIRTUAL', true);
  • Session is created in memory, not saved at the end of the hit.
  • Used for REST-API with token-based authorization — authorization passes, but the session doesn't clutter storage.
php
define('BX_SECURITY_SESSION_VIRTUAL', true);
  • 会话在内存中创建,请求结束时不会保存。
  • 适用于基于令牌授权的REST-API——验证通过但会话不会占用存储资源。

Separated Mode

分离模式

"Hot" kernel data → cookies, "cold" data → backend storage. Enabled in
.settings.php
:
php
'session' => [
    'value' => [
        'mode'     => 'separated',
        'lifetime' => 14400,
        'handlers' => [
            'kernel'  => 'encrypted_cookies',
            'general' => ['type' => 'redis', 'host' => '127.0.0.1', 'port' => 6379],
        ],
    ],
],
  • Fewer calls to Redis/DB.
  • Suitable for high-load: the "hot" part (
    $_SESSION['BX']
    ) goes to cookies/separate kernel storage, the "cold" part — to the general backend (Redis/DB).
「高频」内核数据→Cookie,「低频」数据→后端存储。在
.settings.php
中启用:
php
'session' => [
    'value' => [
        'mode'     => 'separated',
        'lifetime' => 14400,
        'handlers' => [
            'kernel'  => 'encrypted_cookies',
            'general' => ['type' => 'redis', 'host' => '127.0.0.1', 'port' => 6379],
        ],
    ],
],
  • 减少对Redis/数据库的调用次数。
  • 适合高负载场景:「高频」部分(
    $_SESSION['BX']
    )存入Cookie/独立内核存储,「低频」部分存入通用后端(Redis/数据库)。

Storages

会话存储

Specified in
/local/.settings.php
(or
/bitrix/.settings.php
) in the
session.value.handlers.general.type
section:
typeWhenNote
file
Dev, small projectsLock by
flock
→ AJAX slows down
redis
High-load, clustersSupports
servers
(cluster/single), serialization
memcache
Legacy projectsNo persistence
database
When no cache servers
b_user_session
table, not for high-load
/local/.settings.php
(或
/bitrix/.settings.php
)的
session.value.handlers.general.type
段中指定:
类型适用场景说明
file
开发环境、小型项目通过
flock
加锁 → 会拖慢AJAX请求
redis
高负载、集群环境支持
servers
(集群/单节点)、序列化
memcache
遗留项目无持久化能力
database
无缓存服务器的场景存储在
b_user_session
表,不适合高负载

Redis Cluster Example (multi-master)

Redis集群示例(多主节点)

php
'session' => [
    'value' => [
        'mode' => 'default',
        'handlers' => [
            'general' => [
                'type' => 'redis',
                'servers' => [
                    ['host' => '10.0.0.1', 'port' => 6379],
                    ['host' => '10.0.0.2', 'port' => 6379],
                    ['host' => '10.0.0.3', 'port' => 6379],
                ],
                'serializer' => \Redis::SERIALIZER_IGBINARY,
                'persistent' => false,
                'failover'   => \RedisCluster::FAILOVER_DISTRIBUTE,
                'timeout'     => null,
                'readTimeout' => null, // camelCase (session Redis handler)
            ],
        ],
    ],
],
php
'session' => [
    'value' => [
        'mode' => 'default',
        'handlers' => [
            'general' => [
                'type' => 'redis',
                'servers' => [
                    ['host' => '10.0.0.1', 'port' => 6379],
                    ['host' => '10.0.0.2', 'port' => 6379],
                    ['host' => '10.0.0.3', 'port' => 6379],
                ],
                'serializer' => \Redis::SERIALIZER_IGBINARY,
                'persistent' => false,
                'failover'   => \RedisCluster::FAILOVER_DISTRIBUTE,
                'timeout'     => null,
                'readTimeout' => null, // 驼峰命名(会话Redis处理器)
            ],
        ],
    ],
],

Memcache Cluster Example

Memcache集群示例

php
'handlers' => [
    'general' => [
        'type' => 'memcache',
        'servers' => [
            ['host' => '10.0.0.1', 'port' => 11211, 'weight' => 1],
            ['host' => '10.0.0.2', 'port' => 11211],
        ],
    ],
],
php
'handlers' => [
    'general' => [
        'type' => 'memcache',
        'servers' => [
            ['host' => '10.0.0.1', 'port' => 11211, 'weight' => 1],
            ['host' => '10.0.0.2', 'port' => 11211],
        ],
    ],
],

Database

数据库存储

php
'handlers' => [
    'general' => ['type' => 'database'], // b_user_session table
],
php
'handlers' => [
    'general' => ['type' => 'database'], // 存储在b_user_session表
],

General Options

通用配置项

php
'session' => [
    'value' => [
        'lifetime'                 => 14400,  // seconds
        'mode'                     => 'default',
        'regenerateIdAfterLogin'   => true,   // recommended: fixation protection
        'ignoreSessionStartErrors' => false,  // true — hit continues even if Redis is unavailable
        'handlers' => [ ... ],
    ],
],
php
'session' => [
    'value' => [
        'lifetime'                 => 14400,  // 有效期(秒)
        'mode'                     => 'default',
        'regenerateIdAfterLogin'   => true,   // 推荐开启:防止会话固定攻击
        'ignoreSessionStartErrors' => false,  // true表示即使Redis不可用,请求仍会继续
        'handlers' => [ ... ],
    ],
],

Flash Messages (common pattern)

闪存消息(通用模式)

php
$session = Application::getInstance()->getSession();
$session->set('flash.success', 'Post saved');

// next request:
if ($msg = $session->get('flash.success'))
{
    $session->remove('flash.success');
    echo htmlspecialcharsbx($msg);
}
php
$session = Application::getInstance()->getSession();
$session->set('flash.success', '文章已保存');

// 下一次请求中:
if ($msg = $session->get('flash.success'))
{
    $session->remove('flash.success');
    echo htmlspecialcharsbx($msg);
}

Security

安全注意事项

  • After successful login/password change —
    $session->regenerateId()
    . Or
    regenerateIdAfterLogin = true
    in config.
  • Session cookies should be
    HttpOnly
    ,
    Secure
    ,
    SameSite=Lax|Strict
    — configured in main module or via
    session.cookie_*
    in php.ini. See
    bitrix-security
    .
  • 成功登录/修改密码后——调用
    $session->regenerateId()
    。或者在配置中设置
    regenerateIdAfterLogin = true
  • 会话Cookie应设置为
    HttpOnly
    Secure
    SameSite=Lax|Strict
    ——可在主模块配置或php.ini的
    session.cookie_*
    中设置。参考
    bitrix-security
    文档。