一部の Symfony クラスにカスタム ロジックを追加する際に問題が発生しました。
SwitchUserListener
ユーザーが、最初のユーザーよりも多くの権利/役割を持つ別のユーザーに切り替えることができないというチェックを追加したいと思います。
最初の試み
のパラメーターをsecurity_listeners.xml
次のキーで上書きします:
security.authentication.switchuser_listener.classしかし、どこで上書きできますか?
security.yml では機能しませんでした:
security:
...
authentication:
switchuser_listener:
class: Symfony\Component\Security\Http\Firewall\SwitchUserListener
2 回目の試行
SwitchUserListner サービス ID のサービスを上書きします: security.authentication.switchuser_listener
バンドルの service.xml で同じサービスを作成しましたが、クラスが使用または呼び出されませんでした。
別のアイデアは、クラスのみを上書きすることでしたが、それはバンドルに対してのみ機能しますが、SwitchUserListener は SecurityBundle になく、symfony コンポーネント ディレクトリにあり、SecurityBundle を上書きするのは本当に悪い考えだと私には思えました。
3 回目の試行
これで解決策がわかりました: ディスパッチャーが SwitchUserListener の SWTICH_USER イベントのリスナーを呼び出すことに初めて気付きました:
$switchEvent = new SwitchUserEvent($request, $token->getUser());
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
したがって、このイベント タイプ用の特別なタグを使用してサービスを作成するだけで済みます。
<tag name="kernel.event_listener" event="security.switch_user" method="onSecuritySwitchUser" />
そして、指定されたメソッドでチェックを行います。
これは、他の2つよりも優れたソリューションのようです。しかし、まだ問題があります。SwitchUserEvent のリスナーでは、ユーザーが切り替えられたユーザーを終了したい場合、カスタム チェックを無視する必要があります。したがって、要求されたパスを確認する必要があります。ignore if path containts '?switch_user=_exit'
ただし、パス (URL パラメーター) は変更できます。
# app/config/security.yml
security:
firewalls:
main:
# ...
switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
しかし、私のバンドルでは、このパラメーターを読み取ることができませんservice container
。これはSwitchUserListnerクラスのコンストラクターに渡され、そこにプライベート属性として保存され、外部から (リフレクションなしで) アクセスすることはできません。(ここで発生します: SecurityExtension.php
591 行目) では、どうすればよいでしょうか? パラメータを 2 回定義すると、DRY に反します。リフレクションを使用しますか?
もう 1 つのポイントは、サブスクライバー クラスを作成するたびに発生するイベントがあることです。それで、それに対する別の/最良の解決策は何でしょうか?
この質問をするのは、symfony のインターン コンポーネントの何かを追加または上書きしたい場合に同様の問題が発生するためです。
TemplateGuesser
を変更したかったTemplateGuesser
: 特定のバンドルの場合、注釈@Tempalteを持つすべてのテンプレートの場合、テンプレートファイルは、コントローラーと共にTestController#showAction
次のパス に配置する必要があります。
Resources/views/customDir/Test/show.html.twig
そのため、ビューのみを使用するのではなく、ゲッサーを配置してすべてを追加のフォルダーcustomDirに配置する必要があります。特定のテンプレートで関数を使用する場合、ゲッサーはアノテーションを無視する必要があります。render
私は独自のゲッサーを作成し、サービス ID を上書きしました: sensio_framework_extra.view.guesserと比較すると、SwitchUserListener
今回は元のゲッサーの代わりに私のクラスが実際に呼び出されます。ここでは機能するのに、では機能しないのはなぜSwitchUserListener
ですか?
これはまったく良い解決策ですか?また、TemplateGuesser を呼び出す 2 番目のリスナーを追加しようとしました。これは、クラスを持つサービスsensio_framework_extra.view.listener ですSensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener
が、うまくいきませんでした。