【EC-CUBE4】認可アクセスコントロールをsecurity.yamlで設定する方法

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を指定するだけです。

上記の式ではcontainergetParameter メソッドで.envに設定されたECCUBE_FORCE_SSLの値を取得しています。

security.yamlファイルで設定したほうがシンプルで見やすいと思います。

お気軽にコメントをどうぞ

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください