【问题标题】:Symfony : how to set SSL parameters in Doctrine DBAL configuration (YAML)?Symfony:如何在 Doctrine DBAL 配置(YAML)中设置 SSL 参数?
【发布时间】:2015-07-06 07:23:28
【问题描述】:

我想将我的 SSL 证书和密钥文件添加到 Doctrine DBAL 配置中,但我不知道如何实现。

在 PHP 中,我只需要编写类似的内容:

$databaseHandler = new \PDO(
    'mysql:host=my_host;dbname=my_db',
    'username',
    'password',
    array(
        \PDO::MYSQL_ATTR_SSL_KEY   => '.../client-key.pem',
        \PDO::MYSQL_ATTR_SSL_CERT  => '.../client-cert.pem',
        \PDO::MYSQL_ATTR_SSL_CA    => '.../ca-cert.pem'
    )
);

我知道有一个Custom Driver OptiondriverOptions,我看到了this answer,但我不确定如何将它翻译成 YAML。

我觉得我应该写一些接近于:

doctrine:
    dbal:
        driver:   "%database_driver%"
        host:     "%database_host%"
        port:     "%database_port%"
        dbname:   "%database_name%"
        user:     "%database_user%"
        password: "%database_password%"
        charset:  UTF8
        driverOptions:
            PDO::MYSQL_ATTR_SSL_CA: '.../client-key.pem'
            PDO::MYSQL_ATTR_SSL_CERT: '.../client-cert.pem'
            PDO::MYSQL_ATTR_SSL_CA: '.../ca-cert.pem'

但是双冒号并不能真正取悦 YAML...

【问题讨论】:

  • 只使用常量的实际值。 php -r "回显 PDO::MYSQL_ATTR_SSL_CA;"产生 1009,因此将 PDO::MYSQL_ATTR_SSL_CA 替换为 1009。也许有点破解,但数字不会改变。
  • 哦,你学到了一些东西:每个 PHP 类及其扩展的每个属性都有一个唯一的 id?
  • 所有常量都有一个值。虽然该值可能会随着 PHP 的较新版本而改变,但这种情况非常罕见。
  • 好的 :) 非常感谢!同时有人可能知道一种“更清洁”的方式,我会这样做。
  • 使用常量值而不是常量名是个坏主意。现在 php -r "echo PDO::MYSQL_ATTR_SSL_CA;"在 php 5.5.9 中显示 1012

标签: symfony pdo doctrine-orm yaml dbal


【解决方案1】:

自从Symfony 3.2 这变得容易多了:

doctrine:
    dbal:
        <other configs>
        options:
            !php/const:PDO::MYSQL_ATTR_SSL_CA: %ca_cert%
            !php/const:PDO::MYSQL_ATTR_SSL_KEY: %private_key%
            !php/const:PDO::MYSQL_ATTR_SSL_CERT: %public_cert%

【讨论】:

    【解决方案2】:

    我发现了一种比其他方法更简单的方法。 在app/config/config.yml中进行如下设置:

    # Doctrine Configuration
    doctrine:
        dbal:
            driver:   pdo_mysql
            host:     "%database_host%"
            port:     "%database_port%"
            dbname:   "%database_name%"
            user:     "%database_user%"
            password: "%database_password%"
            charset:  UTF8
            # Options for SSL connection
            options:
                MYSQL_ATTR_SSL_CA : %ca_cert%
                MYSQL_ATTR_SSL_KEY : %private_key%
                MYSQL_ATTR_SSL_CERT : %public_cert%
    

    然后在您的app/config/parameters.yml 文件中:

    parameters:
        ...
        # SSL Info
        private_key: /etc/my.cnf.d/certs/client-key.pem
        public_cert: /etc/my.cnf.d/certs/client-cert.pem
        ca_cert: /etc/my.cnf.d/certs/ca-cert.pem
    

    我在 Symfony3 上对此进行了测试,效果很好。上面的路径可能会有所不同,特别是证书可能会有所不同,具体取决于您的发行版和设置方式。

    【讨论】:

    • 也许 Andrew Zhilin 和 @Cerad 都会很高兴,因为不需要指定常量值!
    • 在 Symfony 3.2 和 PHP 5.6.20 上测试过,它对我不起作用。当您指定字符串,并且 PDO 期望 PDO 常量关联数字时,它无法工作。我更喜欢@Samuel Scheiderich 解决方案。经过测试和批准。
    • 嗨@Delphine。我最初尝试/使用过 Samuel(以及 Valentas)的解决方案,但后来我想出了自己的解决方案。我怀疑您的 yaml 文件或其他问题可能存在问题,因为我相信我的解决方案应该有效 - 您可能需要仔细检查。您关于“无法工作”的说法似乎不正确。
    • 我理解您的观点,但我的 PDO 字符串只接收“MYSQL_ATTR_SSL_CA”,而不是转换为相关号码。也许我们可以在 php.in 或 mycf.ini 中配置一些东西来接受两者。我说它对我不起作用,我解释说,对我来说,PDO 收到了字符串而不是数字等价物。也许我不是很清楚..
    • 它不起作用:1)使用tcpdump,你会看到连接没有加密。 2)尝试:SHOW STATUS WHERE Variable_name = 'Ssl_cipher',你会看到变量是空的。
    【解决方案3】:

    通过 yaml(可能还有 xml)配置 Symfony,不允许动态设置键,这意味着您不能使用常量。为了解决这个问题,您可以创建一个额外的 PHP 配置文件,它只处理从常量中生成一个键。

    Gist 中的解决方案在这里:https://gist.github.com/samsch/d5243de3924a8ad10df2

    它利用的两个主要特性是 PHP 配置文件可以使用任何字符串值作为键,包括变量、常量;并且您可以将参数用作其他参数的值(直到我最近尝试过才知道。)

    所以,你在 config.yml 中添加 PHP 配置文件:

    imports:
        - { resource: parameters.yml }
        - { resource: pdo-constants.php }
    

    pdo-constants.php 是这样的:

    <?php
    $container->setParameter("pdo_options", [
        PDO::MYSQL_ATTR_SSL_CA => "%pdo_ca_file%",
    ]);
    

    添加您需要的任何其他常量。

    然后在 parameters.yml 中,您只需要常量的值:

    parameters:
    #...
        pdo_ca_file: /pathtocerts/certs/mysql-ca.pem
    

    现在,我猜想使用另一个使用 PDO 常量的数据库系统会很相似,但我只使用了这个 MySQL。

    【讨论】:

    • 我被 Doc2、PHP 5.6.22 和 Symfony 2 困住了!它没有将“1010”识别为密钥并像证书一样解析它。显然,它告诉它是一个“坏证书”(哦?正常,它是一个密钥..)!如果你的解决方案有效,你真的会拯救我的一天!
    【解决方案4】:

    您应该在options 中使用它们的值,而不是PDO 常量:

    doctrine:
        dbal:
            connections:
                default:
                    driver:   %database_driver%
                    host:     %database_host%
                    port:     %database_port%
                    dbname:   %database_name%
                    password: %database_password%
                    charset:  UTF8
                    options:
                        1010 : %private_key% 
                        1011 : %public_cert% 
                        1012 : %ca_cert%
    

    【讨论】:

    • 不确定你从哪里得到“1012”,但 PDO::MYSQL_ATTR_SSL_CA 是 1009。
    • 使用常量值而不是常量名是个坏主意。现在 php -r "echo PDO::MYSQL_ATTR_SSL_CA;"在 php 5.5.9 中显示 1012。前段时间是 1009。
    【解决方案5】:

    现在是 2020 年,使用 Symfony > 4.2,解决方案是:

    # Doctrine Configuration
    doctrine:
        dbal:
            driver:   pdo_mysql
            host:     "%database_host%"
            port:     "%database_port%"
            dbname:   "%database_name%"
            user:     "%database_user%"
            password: "%database_password%"
            charset:  UTF8
            # Options for SSL connection
            options:
                !php/const PDO::MYSQL_ATTR_SSL_CA : %ca_cert%
                !php/const PDO::MYSQL_ATTR_SSL_KEY : %private_key%
                !php/const PDO::MYSQL_ATTR_SSL_CERT : %public_cert%
    

    来源:symfony.com/doc/4.2/service_container/parameters.html

    使用 Symfony 5.1.8 测试

    【讨论】:

      【解决方案6】:

      An alternative approach 将安装 composer/ca-bundle 以帮助找到 CA 根包的路径,并使用 custom compiler pass 自动向 Doctrine 注册该路径:

      <?php
      
      namespace App\DepenedencyInjection\Compiler;
      
      use Composer\CaBundle\CaBundle;
      use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
      use Symfony\Component\DependencyInjection\ContainerBuilder;
      
      /**
       * Registers a CA root bundle with the PDO MySQL driver used by Doctrine DBAL
       *
       * This allows Doctrine to connect to MySQL instances that force SSL encryption, such as Azure's.
       */
      final class RegisterCABundleWithPDOMysqlDriverPass implements CompilerPassInterface
      {
          /**
           * @inheritDoc
           */
          public function process(ContainerBuilder $container)
          {
              $caPathOrFile = CaBundle::getSystemCaRootBundlePath();
      
              foreach ($container->getParameter('doctrine.connections') ?? [] as $connectionName) {
                  $definition = $container->getDefinition($connectionName);
                  $options = $definition->getArgument(0) ?? [];
                  $options['driverOptions'][\PDO::MYSQL_ATTR_SSL_CA] = $caPathOrFile;
                  $definition->setArgument(0, $options);
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2019-04-24
        • 1970-01-01
        • 2018-06-03
        • 1970-01-01
        • 2011-09-26
        • 2017-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多