简体   繁体   English

PHP FPM Docker ZF1:会话已经开始。 必须先设置会话ID

[英]PHP FPM Docker ZF1: The session has already been started. The session id must be set first

In my dev environment, I'm trying to replace the old heavy Vagrant VM with Docker, using docker-compose : 在我的开发环境中,我尝试使用docker-compose将旧的沉重的Vagrant VM替换为Docker:

version: '2'
services:
    nginx:
        build: ./containers/nginx
        networks:
            mm:
                ipv4_address: 172.25.0.101
        environment:
            APPLICATION_ENV: development
        extra_hosts:
            - "mysite.dev:127.0.0.1"
        ports:
            - 80:80
        links:
            - php
        volumes:
            - ../:/srv

    php:
        build: ./containers/php-fpm
        networks:
            mm:
                ipv4_address: 172.25.0.102
        volumes:
            - ../:/srv
        links:
            - memcached
        ports:
            - 9000:9000

    memcached:
        image: memcached:latest
        ports:
            - 1234:11211
        networks:
            mm:
                ipv4_address: 172.25.0.103

networks:
    mm:
        driver: bridge
        ipam:
            driver: default
            config:
                - subnet: 172.25.0.0/24

But the application is written with ZF1, and whenever I instantiate an Zend_Session_Namespace object just after Zend_Session::start() the following error appears: 但是应用程序是用ZF1编写的,每当我在Zend_Session::start()之后实例化Zend_Session_Namespace对象时,就会出现以下错误:

Zend_Session_Exception: The session has already been started. The session id must be set first. in /srv/mm/vendor/zendframework/zendframework1/library/Zend/Session.php on line 667

I've tried it all, mouting a session path with VOLUME , changing the session.save_path , installing it all again and again, and nothing happens. 我已经尝试了所有操作,使用VOLUME替换了会话路径,更改了session.save_path ,一次又一次地安装了它,但是没有任何反应。

After spent a long debugging this issue I've found the answer for your question. 在花了很长时间调试此问题后,我找到了您问题的答案。 On the second time you call Zend_Session::start() ZF will validate the session id by checking whether it was generated with proper hash_bits_per_character defined by php_ini setting session.hash_bits_per_character or not. 第二次调用Zend_Session::start() ZF将通过检查会话ID是否由php_ini设置session.hash_bits_per_character定义的正确hash_bits_per_character生成来验证会话ID。

/**
 * From Zend_Session 
 */
protected static function _checkId($id)
{
    $saveHandler = ini_get('session.save_handler');
    if ($saveHandler == 'cluster') { // Zend Server SC, validate only after last dash
        $dashPos = strrpos($id, '-');
        if ($dashPos) {
            $id = substr($id, $dashPos + 1);
        }
    }

    $hashBitsPerChar = ini_get('session.hash_bits_per_character');
    if (!$hashBitsPerChar) {
        $hashBitsPerChar = 5; // the default value
    }
    switch($hashBitsPerChar) {
        case 4: $pattern = '^[0-9a-f]*$'; break;
        case 5: $pattern = '^[0-9a-v]*$'; break;
        case 6: $pattern = '^[0-9a-zA-Z-,]*$'; break;
    }
    return preg_match('#'.$pattern.'#', $id);
}

The problem is that for some reason the session id is generated with hash_bits_per_character = 5 instead of hash_bits_per_character = 4 . 问题是由于某种原因,会话ID是使用hash_bits_per_character = 5而不是hash_bits_per_character = 4 So, to solve this problem, all you need to do is force the session.hash_bits_per_character setting before calling Zend_Session::start() for the first time and Zend_Session will check the hash bits using the correct pattern: 因此,要解决此问题,您所需要做的就是在第一次调用Zend_Session::start()之前强制session.hash_bits_per_character设置,Zend_Session将使用正确的模式检查哈希位:

Zend_Session::setOptions(['hash_bits_per_character' => 5]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM