Zendframework 3 - 覆盖CSRF验证器

时间:2017-12-01 09:57:41

标签: validation overwrite zend-framework3 zend-validate zend-servicemanager

我尝试从ZF2迁移到ZF3,但许多 viewHelpers和验证器不起作用。但只有那些覆盖ZendFrameworks viewhelpers / 验证器的人才能工作......

我想要f.e.覆盖CSRF验证器以默认允许更高的超时。

我有以下应用程序配置:

$config = array(
// This should be an array of module namespaces used in the application.
'modules' => array(
    'Zend\Cache',
    'Zend\Db',
    'Zend\Log',
    'Zend\Mail',
    'Zend\Mvc\Console',
    'Zend\Mvc\I18n',
    'Zend\I18n',
    'Zend\Mvc\Plugin\FilePrg',
    'Zend\Form',
    'Zend\Hydrator',
    'Zend\InputFilter',
    'zend\Form',
    'Zend\Filter',
    'Zend\Mvc\Plugin\FlashMessenger',
    'Zend\Mvc\Plugin\Identity',
    'Zend\Mvc\Plugin\Prg',
    'Zend\Navigation',
    'Zend\Paginator',
    'Zend\Serializer',
    'Zend\ServiceManager\Di',
    'Zend\Session',
    'Zend\Router',
    'Zend\Validator',
    'DoctrineModule',
    'DoctrineORMModule',
    'TwbBundle',
    'AssetManager',
    #'Reliv\ElFinder',
    'ZfcUser', //https://github.com/ZF-Commons/ZfcUser
    'ZfcUserDoctrineORM',
    'BjyAuthorize', // https://github.com/bjyoungblood/BjyAuthorize
    'Base',
    'Product',
    'Blog',
    'Admin'
),

// These are various options for the listeners attached to the ModuleManager
'module_listener_options' => array(
    // This should be an array of paths in which modules reside.
    // If a string key is provided, the listener will consider that a module
    // namespace, the value of that key the specific path to that module's
    // Module class.
    'module_paths' => array(
        './module',
        './vendor',
    ),

    // An array of paths from which to glob configuration files after
    // modules are loaded. These effectively override configuration
    // provided by modules themselves. Paths may use GLOB_BRACE notation.
    'config_glob_paths' => array(
        'config/autoload/{,*.}{global,local}.php',
    ),

    // Whether or not to enable a configuration cache.
    // If enabled, the merged configuration will be cached and used in
    // subsequent requests.
    // 'config_cache_enabled' => true,

    // The key used to create the configuration cache file name.
    //'config_cache_key' => $stringKey,

    // Whether or not to enable a module class map cache.
    // If enabled, creates a module class map cache which will be used
    // by in future requests, to reduce the autoloading process.
    // 'module_map_cache_enabled' => true,

    // The key used to create the class map cache file name.
    #'module_map_cache_key' => $stringKey,

    // The path in which to cache merged configuration.
    'cache_dir' => "data/cache/",

    // Whether or not to enable modules dependency checking.
    // Enabled by default, prevents usage of modules that depend on other modules
    // that weren't loaded.
    // 'check_dependencies' => true,
),

// Used to create an own service manager. May contain one or more child arrays.
//'service_listener_options' => array(
//     array(
//         'service_manager' => $stringServiceManagerName,
//         'config_key'      => $stringConfigKey,
//         'interface'       => $stringOptionalInterface,
//         'method'          => $stringRequiredMethodName,
//     ),
// )

// Initial configuration with which to seed the ServiceManager.
// Should be compatible with Zend\ServiceManager\Config.
// 'service_manager' => array(),
);

基本模块的模块配置:

namespace Base;
...
return [
    ...
    'validators' => array(
        'invokables' => [
            \Zend\Validator\Csrf::class => Validator\Csrf::class
        ]
    )
    ...
]

基础\验证\ CSRF:

<?php

namespace Base\Validator;


class Csrf extends \Zend\Validator\Csrf
{
    protected $timeout = 1;

    public function __construct($options = [])
    {
        parent::__construct($options);

        die("THIS DOES NOT GETTING PRINTED! NOR DOES THE BREAKPOINT HIT.");
    }
}

编辑:添加了自动加载配置

composer.json:

"autoload": {
    "psr-4": {
      "Base\\": "module/Base/src/"
    }
  }

编辑2:\ Zend \ Form \ Element \ Csrf的实现可能出现错误?

有趣的是,CsrfValidator只是直接在这里实例化了......

/**
 * Get CSRF validator
 *
 * @return CsrfValidator
 */
public function getCsrfValidator()
{
    if (null === $this->csrfValidator) {
        $csrfOptions = $this->getCsrfValidatorOptions();
        $csrfOptions = array_merge($csrfOptions, ['name' => $this->getName()]);
        $this->setCsrfValidator(new CsrfValidator($csrfOptions));
    }
    return $this->csrfValidator;
} 

Stacktrace(\ Zend \ Validator \ Csrf __construct()中的断点) Stacktrace

StaticPage是我的另一个模块。

我还使用xdebug进行了调试,并在CsrfFactory(return语句)中设置了一个断点,以查看是否使用了(但它不是)。 我想我可以在ZF3中轻松覆盖服务/验证器......我有没有想念?

1 个答案:

答案 0 :(得分:2)

在实例化元素时,可以使用委托者更改附加到表单元素的验证器。本质上,一个委托人允许你(在这种情况下)在构造之后修改表单元素 - 这个想法得到了很好的解释here

在您的情况下,您将创建一个类:

<?php

namespace Base\Delegator;

use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\DelegatorFactoryInterface;
use Zend\Validator\Csrf as CsrfValidator;

class CsrfDelegatorFactory implements DelegatorFactoryInterface
{
    public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback)
    {
        // construct the Csrf form element
        $element = call_user_func($callback);

        // set the validator with chosen timeout and other options
        $element->setCsrfValidator(new CsrfValidator(
            [
                // ...
                'timeout' => 10000
            ]
        ));

        return $element;
    }
}

然后将委托者映射到应用程序module.config.php中的Zend\Form\Element\Csrf

'form_elements' => [
    // ...
    'delegators' => [
        \Zend\Form\Element\Csrf::class => [
            0 => \Base\Delegator\CsrfDelegatorFactory::class
        ],
    ]
],

请注意,这只会将默认情况下分配的验证程序更改为Zend\Form\Element\Csrf,并且不会影响通过其他方式获得的csrf验证程序。