安全


Symfony のセキュリティ システムは非常に強力ですが、セットアップ時に混乱する可能性もあります。この大きな章では、ファイアウォール (ファイアウォール) の構成とユーザーのロードから、アクセスの拒否とユーザー オブジェクトの取得まで、アプリケーションのセキュリティを段階的に設定する方法を学習します。ニーズによっては、初期設定を行うのが面倒な場合があります。しかし、一度完成すると、Symfony のセキュリティ システムは柔軟性があり、(願わくば) 楽しく使用できるようになります。

言いたいことがたくさんあるため、この章はいくつかの本にまとめられています。

  1. 初期化security.yml 設定 (authentication /verification );

  2. プログラムへのアクセスが拒否されました (authorization/authorization );

  3. 現在のユーザー オブジェクト;

これらは、ログアウト 暗号化ユーザー パスワード など、多くの小さな (それでも魅力的な) 部分に分割されます。

1) security.yml 設定の初期化 (認証/検証)

##セキュリティ システムは

app/config/security.yml 設定で実行されます。デフォルトの構成は次のようになります。

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    'providers' => array(
        'in_memory' => array(
            'memory' => null,
        ),
    ),
    'firewalls' => array(
        'dev' => array(
            'pattern'    => '^/(_(profiler|wdt)|css|images|js)/',
            'security'   => false,
        ),
        'default' => array(
            'anonymous'  => null,
        ),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <provider name="in_memory">
            <memory />
        </provider>         <firewall name="dev"            pattern="^/(_(profiler|wdt)|css|images|js)/"            security="false" />         <firewall name="default">
            <anonymous />
        </firewall>
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:
    providers:
        in_memory:
            memory: ~
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        default:
            anonymous: ~

firewalls キーは、セキュリティ構成の core です。 dev ファイアウォールは重要ではありません。単に Symfony 開発ツール、つまり /_profiler および /_wdt の下にある URL がブロックされないことを保証するだけです。セキュリティによってブロックされています。

リクエストを、リクエスト内の他の詳細 (ホストなど) と照合することもできます。詳細と例については、

ファイアウォールを特定のリクエストに制限する方法を参照してください。

他のすべての URL は、

default ファイアウォールによって処理されます (pattern キーがない場合は、all URL と一致できることを意味します) )。ファイアウォールはセキュリティ システムと考えることができるため、通常はメインのファイアウォールを 1 つだけ使用するのが合理的です。ただし、これは、すべての URL を認証する必要があるという意味ではありません。anonymous キーがこれを処理します。実際、今ホームページにアクセスすると、アクセスできるようになり、anon. として「認証」されたことがわかります。 [認証済み] の横の [はい] に騙されないでください。あなたはまだ単なる匿名ユーザーです:

#特定の URL へのアクセスを拒否する方法については後で説明します。またはコントローラー (アクションの) 。 11.png

セキュリティは
高度に構成可能であり、すべての構成オプションは、いくつかの追加手順とともに
セキュリティ構成リファレンス

に示されています。

A) 「ユーザーを認証できるようにする方法」を構成する

ファイアウォールの主な仕事は、ユーザーが認証できるようにするための 方法 を構成することです。認証されました。ログインフォームは必要ですか?それともHTTP基本認証でしょうか?それともAPIトークンでしょうか?それとも上記のすべてですか?

HTTP 基本認証 (古いポップアップ ボックス) から始めましょう。この機能を有効にするには、http_basic をファイアウォールに追加します。

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...
    'firewalls' => array(
        // ...
        'default' => array(
            'anonymous'  => null,
            'http_basic' => null,
        ),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <firewall name="default">
            <anonymous />
            <http-basic />
        </firewall>
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:
            anonymous: ~
            http_basic: ~
それはとても簡単です。効果をテストするには、ユーザーにログインしてページを表示させる必要があります。面白くするために、/admin の下に新しいページを作成します。たとえば、注釈を使用する場合は、次のコードを作成します。
// src/AppBundle/Controller/DefaultController.php
// ... use 
Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Symfony\Component\HttpFoundation\Response; class DefaultController extends Controller{
   /**
     * @Route("/admin")
     */
    public function adminAction()
    {
        return new Response('<html><body>Admin page!</body></html>');
    }}

次に、security.ymlaccess_control エントリを追加して、ユーザーにアクセスを許可します。まずログインして URL にアクセスします:

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...
    'firewalls' => array(
        // ...
        'default' => array(
            // ...
        ),
    ),
   'access_control' => array(
       // require ROLE_ADMIN for /admin*
        array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <firewall name="default">
            <!-- ... -->
        </firewall>         <!-- require ROLE_ADMIN for /admin* -->
        <rule path="^/admin" role="ROLE_ADMIN" />
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:            # ...
    access_control:        # require ROLE_ADMIN for /admin*
        - { path: ^/admin, roles: ROLE_ADMIN }

/admin にアクセスすると、HTTP 基本認証のポップアップ ログインが表示されます:

222.png

しかし、どのような ID でログインしますか?ユーザー(情報)はどこから来るのか?

従来のフォームを使用したいですか?とても良い! 従来のログイン フォームを作成する方法を参照してください。他にどのような (認証) 方法がサポートされていますか?独自の を構築するには、Configuration Reference または を参照してください。

プログラムが Google、Facebook、Twitter などのサードパーティ サービスを通じてログインを完了する場合は、HWIOAuthBundle コミュニティ バンドルを参照してください。 。

B) 「ユーザーのロード方法」を設定する

ユーザー名を入力すると、Symfony はユーザーの情報をどこかからロードします。これはいわゆる「ユーザープロバイダー」であり、それを構成するのはあなたの責任です。 Symfony には、データベースからユーザーを ロードする方法が組み込まれていますが、独自のユーザー プロバイダーを 作成することも可能です。 最も簡単な方法 (ただし多くの制限があります) は、プログラムされたユーザーを

security.yml

ファイルから直接ロードするように Symfony を設定することです。これは「メモリ内」プロバイダーと呼ばれますが、「構成内」プロバイダーと考える方が適切です。

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    'providers' => array(
        'in_memory' => array(
            'memory' => array(
                'users' => array(
                    'ryan' => array(
                        'password' => 'ryanpass',
                        'roles' => 'ROLE_USER',
                    ),
                    'admin' => array(
                        'password' => 'kitten',
                        'roles' => 'ROLE_ADMIN',
                    ),
                ),
            ),
        ),
    ),
    // ...));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <provider name="in_memory">
            <memory>
                <user name="ryan" password="ryanpass" roles="ROLE_USER" />
                <user name="admin" password="kitten" roles="ROLE_ADMIN" />
            </memory>
        </provider>
        <!-- ... -->
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:
    providers:
        in_memory:
            memory:
                users:
                    ryan:
                        password: ryanpass
                        roles: 'ROLE_USER'
                    admin:
                        password: kitten
                        roles: 'ROLE_ADMIN'    # ...

ファイアウォール

と同様に、複数の プロバイダー#を使用できます。 ## ですが、必要なのはほとんど 1 つだけです。 Indeed が複数ある場合は、ファイアウォールの provider キー (例: provider: in_memory) ## で「どの を使用するか」を設定できます。 #”プロバイダー。 参照

複数のユーザー プロバイダーの使用方法
では、複数のプロバイダーのセットアップの詳細を確認します。

ユーザー名 admin とパスワード kitten を使用してログインしてみます。エラーが表示されるはずです。

アカウント "Symfony\Component\Security\Core\User\User" にエンコーダーが設定されていません。

これを修正するには、エンコーダーを追加します キー:

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'encoders' => array(
        'Symfony\Component\Security\Core\User\User' => 'plaintext',
    ),
    // ...));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <encoder class="Symfony\Component\Security\Core\User\User"            algorithm="plaintext" />
        <!-- ... -->
    </config></srv:container>
YAML:app/config/security.ymlsecurity:    # ...
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext    # ...

ユーザー プロバイダーはユーザー情報を読み込み、User オブジェクトに配置します。データベースからユーザーを ロードする場合、または他のソースから をロードする場合は、カスタム User クラスを使用する必要があります。ただし、「メモリ内」プロバイダーを使用すると、Symfony\Component\Security\Core\User\User オブジェクトが直接提供されます。
どのようなユーザー クラスを使用する場合でも、パスワード暗号化アルゴリズムが何であるかを Symfony に伝える必要があります。この場合、パスワードは平文ですが、すぐに

bcrypt

に変更する必要があるでしょう。 今更新するとログインされます。 Web デバッグ ツールバーには、自分が誰であるか、そして自分の役割が何であるかが表示されます。

4444t.pngユーザーとしてログインしている場合、この URL には

ROLE_ADMIN

が必要なので、 ryan、アクセスは拒否されます。詳細については、次の [URL 保護条件 (access_control](#catalog9)) を参照してください。 Doctrine Orm ユーザー、それは簡単です! 詳細については、データベースからセキュリティ システム ユーザーをロードする方法 (エンティティ プロバイダー) を参照してください。

C) ユーザー パスワードの暗号化

ユーザーが security.yml、データベース、またはその他の場所に保存されているかどうかに関係なく、ユーザーのパスワードを暗号化する必要があります。利用可能な最良のアルゴリズムは

bcrypt

です。
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'encoders' => array(
        'Symfony\Component\Security\Core\User\User' => array(
            'algorithm' => 'bcrypt',
            'cost' => 12,
        )
    ),
    // ...));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>        <!-- ... -->         <encoder class="Symfony\Component\Security\Core\User\User"            algorithm="bcrypt"            cost="12" />         <!-- ... -->    </config></srv:container>

YAML:# app/config/security.ymlsecurity:    # ...
    encoders:
        Symfony\Component\Security\Core\User\User:
            algorithm: bcrypt
            cost: 12
## もちろん、ユーザー パスワードが必要になります。この指定されたアルゴリズムによって暗号化されます。 (config.yml で) ハードコーディングされているユーザーの場合は、組み込みコマンド




##

1

を使用して実行できます。

$  php bin/console security:encode-password
##

次のような内容が表示されます (パスワードは暗号化されています):

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'providers' => array(
        'in_memory' => array(
            'memory' => array(
                'users' => array(
                    'ryan' => array(
                        'password' => 'a$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli',
                        'roles' => 'ROLE_USER',
                    ),
                    'admin' => array(
                        'password' => 'a$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G',
                        'roles' => 'ROLE_ADMIN',
                    ),
                ),
            ),
        ),
    ),
    // ...));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <provider name="in_memory">
            <memory>
                <user name="ryan" password="a$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli" roles="ROLE_USER" />
                <user name="admin" password="a$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G" roles="ROLE_ADMIN" />
            </memory>
        </provider>
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:    # ...
    providers:
        in_memory:
            memory:
                users:
                    ryan:
                        password: a$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli
                        roles: 'ROLE_USER'
                    admin:
                        password: a$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G
                        roles: 'ROLE_ADMIN'

これで、すべては以前と同じになります。しかし、動的ユーザー (データベースなど) があり、そのパスワードがデータベースに保存される前に暗号化される場合、どうすればそれらをプログラムで暗号化できるでしょうか?心配しないでください。詳細については、「パスワードを手動で暗号化する」を参照してください。

この暗号化アルゴリズムがサポートされているかどうかは、PHP のバージョンによって異なりますが、

hash_algos PHP 関数によって返されるアルゴリズムや、その他のアルゴリズム (## など) が含まれます。 #bcrypt) がサポートされています。例として、セキュリティ リファレンスencoders オプション キーを参照してください。 ユーザーごとに異なるアルゴリズムを使用することも可能です。詳細については、

パスワード暗号化アルゴリズムを動的に選択する方法

を参照してください。

D) 設定が完了しました。 ###¶#########おめでとう!これで、HTTP 基本認証に基づいた「認証システム」が動作し、security.yml ファイルからユーザーが読み込まれるようになりました。

設定に応じて、次の手順があります:

ユーザー ログインのさまざまな方法 (

ログイン フォーム
  • some など) を構成します。完全にカスタマイズ可能

    ;

    データベース
  • その他のソースなどのさまざまなソースからユーザーを読み込みます

    ;

    Authorization
  • 」セクションでは、アクセスの拒否、ユーザー オブジェクトの読み込み、ロールの操作方法を学習します。
  • 2) アクセス、ロールなどの拒否認証方法

これで、ユーザーは http_basic またはその他の方法を介してプログラムにログインできるようになります。すばらしい!ここで、アクセスを拒否し、ユーザー オブジェクトを操作する方法を学ぶ必要があります。これは

authorization

(認可) と呼ばれ、その役割は、ユーザーが特定のリソース (URL、モデル オブジェクト、呼び出されたメソッドなど) にアクセスできるかどうかを判断することです。 認可プロセスは 2 つの異なる側面に分かれています:

ユーザーはログイン時に特定のロールのセットを受け取ります。

ROLE_ADMIN
    など) 。
  1. リソース (URL、コントローラーなど) にアクセスするには特定の「属性」 (通常は

    ROLE_ADMIN
  2. などのロール) が必要となるようにコードを追加します。 。
  3. ロール (
ROLE_ADMIN
など) に加えて、他の属性/文字列 (
EDIT# など) も使用できます。 ## ) リソースを保護し、投票者または Symfony の ACL システムを使用して有効にします。これは、ユーザー A がオブジェクト B (たとえば、ID 5 の製品) を「編集」できるかどうかを確認する必要がある場合に便利です。

アクセス制御リスト (ACL): 個々のデータベース オブジェクトの保護を参照してください。

ロール/ロール

ユーザーはログインすると、一連のロール (ROLE_ADMIN など) を受け取ります。上記の例では、これら (ロール) は security.yml にハードコーディングされています。データベースからユーザーをロードする場合、ユーザーはテーブルの列に保存される必要があります。

ユーザーに割り当てるすべてのロールは、ROLE_ プレフィックスで始まる必要があります。そうしないと、通常の方法では Symfony のセキュリティ システムによって操作されません (高度な手段を使用しない限り、そうでない場合は、FOO のようなロールをユーザーに割り当ててから、below のようなチェックを行います) FOO は機能しません)。

ロールは非常にシンプルで、基本的にはニーズに応じて作成する文字列です。たとえば、Web サイトのブログの管理セクションへのアクセスを制限する場合は、ROLE_BLOG_ADMIN ロールを使用してそれを保護できます。ロールを他の場所で定義する必要はなく、ただ使用を開始することができます。

各ユーザーが少なくとも 1 つの ロールを持っていることを確認してください。そうでない場合、ユーザーは未検証として扱われます。一般的なアプローチは、 一般ユーザーに ROLE_USER を与えることです。

ロール レベルを指定することもできます。現時点では、特定のロールを所有しているということは、他のロールも所有していることを意味します。

アクセスを拒否するコードを追加する

何かへのアクセスを拒否するには、2 つの方法があります:

  • security.yml で access_control を使用して、URL 条件付き保護 (/admin/* など) を使用します。これは簡単ですが、あまり柔軟ではありません;

  • コードで security.authorization_checker サービスを使用します;

合格条件URL を保護するためのマッチング (access_control)

プログラムの特定の部分を保護する最も基本的な方法は、URL に対して完全な条件付きマッチングを実行することです。正規表現

^/admin に一致するページには ROLE_ADMIN が必要であることを前に説明しました:

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'firewalls' => array(
        // ...
        'default' => array(
            // ...
        ),
    ),
   'access_control' => array(
       // require ROLE_ADMIN for /admin*
        array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <firewall name="default">
            <!-- ... -->
        </firewall>         <!-- require ROLE_ADMIN for /admin* -->
        <rule path="^/admin" role="ROLE_ADMIN" />
    </config></srv:container>

YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:            # ...
    access_control:        # require ROLE_ADMIN for /admin*
        - { path: ^/admin, roles: ROLE_ADMIN }

(URL が属する) 領域全体を保護できるのは良いことですが、コントローラーの 特定のアクション を保護したい場合もあります。

必要に応じて、URL 一致条件を好きなだけ定義できます。各条件は正規表現です。 ただし、 では、 と 1 つの のみが一致します。 symfony は (ファイル内の) 先頭から検索を開始し、URL に一致する access_control エントリを見つけるとすぐに終了します。

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'access_control' => array(
        array('path' => '^/admin/users', 'role' => 'ROLE_SUPER_ADMIN'),
        array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <rule path="^/admin/users" role="ROLE_SUPER_ADMIN" />
        <rule path="^/admin" role="ROLE_ADMIN" />
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:    # ...
    access_control:
        - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN }
        - { path: ^/admin, roles: ROLE_ADMIN }

パスに ^ を追加すると、URL が「通常の条件に従って始まる」場合にのみ一致することになります。たとえば、パスに /admin (^ を除く) のみが含まれる場合、/admin/foo だけでなく /foo/ にも一致します。 ### この種。

access_control の仕組みを理解する

access_control パーツは非常に強力ですが、その仕組みを理解していない場合は、 原則、それは危険な場合もあります(結局のところ、セキュリティが関係します)。 access_control URL の照合に加えて、IP アドレス、ホスト名、HTTP メソッドの照合も可能です。これは、ユーザーを URL 条件の https バージョンにリダイレクトするために使用することもできます。

これらすべてを理解するには、

セキュリティの access_control の仕組みを参照してください。

コントローラーとコードの他の部分を保護する

コントローラーでは、簡単にアクセスを拒否できます:

// ... public function helloAction($name){
    // The second parameter is used to specify on what object the role is tested.
    // 第二个参数用于指定“要将role作用到什么对象之上”
    $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');     // Old way / 老办法:
    // if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
    //     throw $this->createAccessDeniedException('Unable to access this page!');
    // }     // ...}

どちらの場合も、特殊な

AccessDeniedException がスローされ、最終的に Symfony 内で 403 HTTP 応答がトリガーされます。 #########それでおしまい!ユーザーがまだログインしていない場合は、ログインするように求められます (ログイン ページにリダイレクトされるなど)。 ログインしていても
ROLE_ADMIN

ロールを持っていない場合、403 アクセス拒否ページが表示されます (このページは

カスタマイズ可能です)。ログインしていて正しい役割を持っている場合、コードは実行を続けます。 SensioFrameworkExtraBundle のおかげで、コントローラーでアノテーションを使用できるようになりました。

// ...use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; /**
 * @Security("has_role('ROLE_ADMIN')")
 */public function helloAction($name){
    // ...}
詳細については、FrameworkExtraBundle を参照してください。

テンプレートでのアクセス制御


現在のユーザーがテンプレートでロールを持っているかどうかを確認したい場合は、組み込みの # を使用できます。 ##is_granted( )

ヘルパー関数:

PHP:<?php if ($view['security']->isGranted('ROLE_ADMIN')): ?>
    <a href="...">Delete</a><?php endif ?>
Twig:{% if is_granted('ROLE_ADMIN') %}
    <a href="...">Delete</a>{% endif %}

他のサービスを保護する

「コントローラーを保護する」などの同様のコードを作成すると、Symfony 内のどこでも保護できます。電子メールを送信するためのサービス (つまり、php クラス) があるとします。このクラスの使用を、使用場所に関係なく、特定のユーザーのみに制限できます。

詳細については、プログラム内のサービスとメソッドを保護する方法を参照してください。

ユーザーがログインしているかどうかを確認します (IS_AUTHENTICATED_FULLY)

これまでのところ、役割ベースのアクセス (ROLE_# で始まるアクセス) を確認しました。 ## prefix ユーザーに割り当てられる文字列です。ただし、ユーザーがログインしているかどうかを のみ確認したい (ロールの有無は気にしない) 場合は、IS_AUTHENTICATED_FULLY: // を使用できます。 ... public function helloAction ($name){

    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw $this->createAccessDeniedException();
    }     // ...}

もちろん
access_control

でも使用できます。

IS_AUTHENTICATED_FULLY

はロールではありませんが、その動作の一部はロールに似ており、ログインに成功したすべてのユーザーがそのようなロールを持ちます。実際、同様の特別な属性が 3 つあります:

    ##IS_AUTHENTICATED_REMEMBERED
  • :

    すべての ログイン ユーザーは、" 経由でログインしている場合でも、この属性を持ちます。クッキーを覚えてください」とログインします。 remember me 機能 を使用しない場合でも、この属性を通じてユーザーがログインしているかどうかを確認できます。

    ##IS_AUTHENTICATED_FULLY
  • :
  • IS_AUTHENTICATED_REMEMBERED

    と似ていますが、より堅牢です。 「記憶する Cookie」の IS_AUTHENTICATED_REMEMBERED のみに基づいてログインするユーザーには、IS_AUTHENTICATED_FULLY がありません。

    IS_AUTHENTICATED_ANONYMOUSLY
  • :
  • すべての

    ユーザー (匿名ユーザーも含む) がこの属性を持ちます - URL が whitelist# # に配置されている場合# アクセスできることを確認すると便利です。詳細については、セキュリティの access_control の仕組みを参照してください。 テンプレートで式を使用することもできます:

    PHP:<?php if ($view['security']->isGranted(new Expression(
        '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'))): ?>
        <a href="...">Delete</a><?php endif; ?>

    Twig:{% if is_granted(expression(
        '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())')) %}
        <a href="...">Delete</a>{% endif %}
  • 式とセキュリティの詳細については、セキュリティ: 複雑なアクセス制御式.

    アクセス制御リスト (ACL): 個々のデータベース オブジェクトの保護

    ユーザーがトピックの下にコメントを残せるブログをデザインしていると想像してください。また、ユーザーが自分のコメントを編集できるようにする必要がありますが、他のユーザーは編集できないようにする必要があります。さらに、管理者ユーザーは、all 個のコメントを編集できるようにする必要があります。

    これを行うには、2 つのオプションがあります:

    • 有権者 ユーザーが独自のビジネス ロジックを作成できるようにする (例: ユーザーはこの記事を編集できます)そのまま作成しました)アクセスを確認します。このオプションは、上記の問題を解決するのに十分な柔軟性を備えているため、使用することもできます。

    • ACLs any オブジェクトを任意の ユーザー Any# に割り当てることができるデータベース構造を作成できます。 ## アクセス権 (例: 編集、表示)。 ACL を使用するには、管理者ユーザーが何らかの管理インターフェイスを通じてシステムへのカスタム アクセスを許可する必要があります。

    • どちらの場合も、前の例と同様の方法を使用してアクセス拒否を実装する必要があります。

    ユーザー オブジェクトを取得する

    検証後、

    security.token_storage

    を通じて現在のユーザーの User にアクセスできます。サービスオブジェクト。コントローラーで次のように記述します:

    public function indexAction(){
        if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
            throw $this->createAccessDeniedException();
        }     $user = $this->getUser();     // the above is a shortcut for this / 上面的写法是通过以下取法(再进行授权)的快捷方式
        $user = $this->get('security.token_storage')->getToken()->getUser();}


    ユーザーはオブジェクトになり、オブジェクトが属するクラスは
    ユーザー プロバイダー#によって異なります。 ##。


    ##3.2

    メソッド シグネチャを介したユーザー関数の取得は、Symfony 3.2 から導入されました。

    Controller を継承した場合でも、$this->getUser() を呼び出して取得できます。

    これで、 User オブジェクトに基づいて任意のメソッドを呼び出すことができます。たとえば、User オブジェクトに getFirstName() メソッドがある場合、それを使用できます。

    use Symfony\Component\HttpFoundation\Response;
    // ... public function indexAction(){
      // ...     return new Response('Well hi there '.$user->getFirstName());}

    ユーザーがログインしているかどうかを常に検出します


    ユーザーの最初の確認は非常に重要です。ログインしていない場合、

    $usernull または anon. 文字列のいずれかになります。待って、なぜですか?はい、変です。ログインしていない場合、技術的にはユーザーは anon. である必要がありますが、コントローラーの getUser() ショートカット メソッドは便宜上これを null# に変換します ## 。 UserInterface のタイプ ヒントを使用し、ログインがオプションである場合、パラメータに null 値を設定できます:

    public function indexAction(UserInterface $user = null){
        // $user is null when not logged-in or anon.
        // 当用户没有登陆,或者是anno.时,$user是null}
    ビューは次のとおりです。常にそうする必要があります。 User オブジェクトを使用する前に、ユーザーがログインしているかどうかを確認してください。これは、

    isGranted

    メソッド (または access_control) を使用して行うことができます。テンプレート ユーザー

    オブジェクトを取得するには、twig テンプレートの app.user キーを使用できます:

    // yay! Use this to see if the user is logged in// 耶!使用这个来查看用户是否已登陆if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw $this->createAccessDeniedException();} // boo :(. Never check for the User object to see if they're logged in// 哄!:(. 切勿通过检查User对象来判断用户是否已登陆if ($this->getUser()) { }
    PHP:<?php if ($view['security']->isGranted('IS_AUTHENTICATED_FULLY')): ?>
        <p>Username: <?php echo $app->getUser()->getUsername() ?></p><?php endif; ?>

    Logging out/ログアウト

    ##http-basic 認証でファイアウォールを使用している場合、終了する方法がないことに注意してください: log out
    が唯一の方法です。リクエストごとにユーザー名とパスワードの送信を停止するようにブラウザに指示するだけです。多くの場合、ブラウザのキャッシュをクリアするか再起動すると解決します。特定の Web 開発ツールも役立つ場合があります。

    通常は、ユーザーがログアウトできるようにする必要があります。幸いなことに、logout 構成パラメータを有効にすると、ファイアウォールがこれを自動的に処理するのに役立ちます:

    Twig:{% if is_granted('IS_AUTHENTICATED_FULLY') %}
        <p>Username: {{ app.user.username }}</p>{% endif %}
    PHP:// app/config/security.php$container->loadFromExtension('security', array(
        // ...     'firewalls' => array(
            'secured_area' => array(
                // ...
                'logout' => array('path' => '/logout', 'target' => '/'),
            ),
        ),));
    Twig:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
            <!-- ... -->         <firewall name="secured_area">
                <!-- ... -->
                <logout path="/logout" target="/" />
            </firewall>
        </config></srv:container>
    次に、この URL のルートを作成する必要があります (ただし、コントローラは必要ありません)。

    YAML:# app/config/security.ymlsecurity:    # ...
        firewalls:
            secured_area:            # ...
                logout:
                    path:   /logout
                    target: /
    rree
    PHP:// app/config/routing.phpuse Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\Route; $collection = new RouteCollection();$collection->add('logout', new Route('/logout')); return $collection;
    ###それでおしまい! Symfony は、ユーザーを

    /logout (または設定した任意の path オプション) に送信することで、現在のユーザーの認証を解除します。

    ユーザーがログアウトすると、定義された

    target パラメーター (homepage など) に対応するパスにリダイレクトされます。

    ログアウト後にさらに興味深いことを行う必要がある場合は、

    success_handler キーを追加して「ログアウト成功ハンドラー」を指定できます)。次のように入力します。サービス定義の ID サービスのクラスは、LogoutSuccessHandlerInterface インターフェースを実装する必要があります。 セキュリティ構成リファレンスを参照してください。

    レベル別のロール

    多数のロールをユーザーに関連付ける代わりに、ロール階層を作成することで、一連のロールを定義できます。 「ロール継承ルール」の:

    XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://Symfony.com/schema/routing"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://Symfony.com/schema/routing        http://Symfony.com/schema/routing/routing-1.0.xsd">     <route id="logout" path="/logout" /></routes>
    YAML:# app/config/routing.ymllogout:
        path: /logout

    PHP:// app/config/security.php$container->loadFromExtension('security', array(
        // ...     'role_hierarchy' => array(
            'ROLE_ADMIN'       => 'ROLE_USER',
            'ROLE_SUPER_ADMIN' => array(
                'ROLE_ADMIN',
                'ROLE_ALLOWED_TO_SWITCH',
            ),
        ),));
    上記の構成では、ユーザー

    ROLE_ADMINROLE_USER ロールも持ちます。 ROLE_SUPER_ADMIN ロール。これには、ROLE_ADMINROLE_ALLOWED_TO_SWITCH、および ROLE_USER (ROLE_ADMIN から継承) もあります。

    まとめ

    ああ、よくやった!セキュリティの基本以上のことを学びました。最も難しいのは、認証戦略 (API トークンなど)、複雑な認可ロジック、その他多くのものの定義などのカスタム要件がある場合です (セキュリティは本質的に複雑であるため)。

    幸いなことに、ここにはさまざまな状況を明確にすることを目的とした記事がたくさんあります。

    セキュリティリファレンスも参照してください。多くの構成オプションは詳しく説明されていませんが、完全な構成ツリーを確認することは役立ちます。 ######幸運を!