EC-CUBE4は認可アクセスコントロールをDIの拡張機能を利用して設定しています。
namespace Eccube\DependencyInjection;
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Configuration as DoctrineBundleConfiguration;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
class EccubeExtension extends Extension implements PrependExtensionInterface
{
/**
* Loads a specific configuration.
*
* @throws \InvalidArgumentException When provided tag is not defined in this extension
*/
public function load(array $configs, ContainerBuilder $container)
{
}
/**
* Allow an extension to prepend the extension configurations.
*/
public function prepend(ContainerBuilder $container)
{
// FrameworkBundleの設定を動的に変更する.
$this->configureFramework($container);
// プラグインの有効無効判定および初期化を行う.
$this->configurePlugins($container);
}
protected function configureFramework(ContainerBuilder $container)
{
$forceSSL = $container->resolveEnvPlaceholders('%env(ECCUBE_FORCE_SSL)%', true);
// envから取得した内容が文字列のため, booleanに変換
if ('true' === $forceSSL) {
$forceSSL = true;
} elseif ('false' === $forceSSL) {
$forceSSL = false;
}
// SSL強制時は, httpsのみにアクセス制限する
$accessControl = [
['path' => '^/%eccube_admin_route%/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
['path' => '^/%eccube_admin_route%/', 'roles' => 'ROLE_ADMIN'],
['path' => '^/mypage/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
['path' => '^/mypage/withdraw_complete', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
['path' => '^/mypage/change', 'roles' => 'IS_AUTHENTICATED_FULLY'],
['path' => '^/mypage/', 'roles' => 'ROLE_USER'],
];
if ($forceSSL) {
foreach ($accessControl as &$control) {
$control['requires_channel'] = 'https';
}
}
// security.ymlでは制御できないため, ここで定義する.
$container->prependExtensionConfig('security', [
'access_control' => $accessControl,
]);
}
おそらくSSL強制の切り替えを動的に行いたいためだと思いますが、SSL強制の動的切り替えはyamlファイルでも設定可能です。
設定方法は以下の通りです。
security:
access_control:
- { path: ^/%eccube_admin_route%/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: "@=container.getParameter('eccube_force_ssl') ? 'https' : 'http'"}
- { path: ^/%eccube_admin_route%/, roles: ROLE_ADMIN, requires_channel: "@=container.getParameter('eccube_force_ssl') 'https' : 'http'"}
- { path: ^/mypage/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: "@=container.getParameter('eccube_force_ssl') 'https' : 'http'"}
- { path: ^/mypage/withdraw_complete, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: "@=container.getParameter('eccube_force_ssl') ? 'https' : 'http'"}
- { path: ^/mypage/change, roles: IS_AUTHENTICATED_FULLY, requires_channel: "@=container.getParameter('eccube_force_ssl') ? 'https' : 'http'"}
- { path: ^/mypage/, roles: ROLE_USER, requires_channel: "@=container.getParameter('eccube_force_ssl') ? 'https' : 'http'"}
.envで設定されたSSL強制の有効・無効は以下の式で取得しています。
@=container.getParameter('eccube_force_ssl')
Symfonyのサービスコンテナは特定の値をサービスに挿入できる「式」をサポートしていて、yamlファイルで式を使用する場合は「@=」のプレフィックスを付ける必要があります。
詳しくはSymfonyドキュメントの「How to Inject Values Based on Complex Expressions」をご確認ください。
コンテナにアクセスする場合は、先頭に@=
をついてcontainer
を指定するだけです。
上記の式ではcontainer
のgetParameter
メソッドで.envに設定されたECCUBE_FORCE_SSL
の値を取得しています。
security.yamlファイルで設定したほうがシンプルで見やすいと思います。