【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ファイルで設定したほうがシンプルで見やすいと思います。

1件のコメント

  1. 販売管理システム(別サーバーのDB)から顧客情報をAPIで取得してその情報でマイページにログインしたいのですが、認証に引っかかって失敗してしまいます。とりあえず認証をパスしたい場合は何を変更すればいいんでしょうか?

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

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