Symfony:如何在 Doctrine DBAL 配置(YAML)中设置 SSL 参数?
Symfony : how to set SSL parameters in Doctrine DBAL configuration (YAML)?
我想将我的 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 Option driverOptions
, and I saw 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...
而不是 PDO
常量,您应该在 options
:
中使用它们的值
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%
通过 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。
我发现了一个比其他方法简单得多的方法。
在 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 上对此进行了测试,效果很好。上面的路径可能会有所不同,特别是证书可能会有所不同,具体取决于您的发行版和设置方式。
自从 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%
An alternative approach would be installing composer/ca-bundle
to help find the path to the CA root bundle and use a 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);
}
}
}
现在 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 测试
我在 docker 上使用 PHP 5.6.40,并且一直在调试为什么我的本地无法通过 ssl 连接。出于某种奇怪的原因,它需要 const 1009 而不是 1012。在这里删除这个答案以防将来有人偶然发现它。
doctrine:
dbal:
connections:
default:
options:
1001: true
1009: %ssl_cert_path%
我想将我的 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 Option driverOptions
, and I saw 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...
而不是 PDO
常量,您应该在 options
:
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%
通过 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。
我发现了一个比其他方法简单得多的方法。
在 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 上对此进行了测试,效果很好。上面的路径可能会有所不同,特别是证书可能会有所不同,具体取决于您的发行版和设置方式。
自从 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%
An alternative approach would be installing composer/ca-bundle
to help find the path to the CA root bundle and use a 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);
}
}
}
现在 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 测试
我在 docker 上使用 PHP 5.6.40,并且一直在调试为什么我的本地无法通过 ssl 连接。出于某种奇怪的原因,它需要 const 1009 而不是 1012。在这里删除这个答案以防将来有人偶然发现它。
doctrine:
dbal:
connections:
default:
options:
1001: true
1009: %ssl_cert_path%